Skip to content

Commit 618904e

Browse files
committed
Implement AlwaysFalsE
1 parent a0790b0 commit 618904e

File tree

6 files changed

+85
-28
lines changed

6 files changed

+85
-28
lines changed

coderd/database/modelqueries.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"strings"
77

8+
"github.com/coder/coder/coderd/rbac/regosql"
9+
810
"github.com/lib/pq"
911

1012
"github.com/coder/coder/coderd/rbac"
@@ -29,7 +31,9 @@ type templateQuerier interface {
2931
}
3032

3133
func (q *sqlQuerier) GetAuthorizedTemplates(ctx context.Context, arg GetTemplatesWithFilterParams, prepared rbac.PreparedAuthorized) ([]Template, error) {
32-
authorizedFilter, err := prepared.CompileToSQL(rbac.ConfigWithACL())
34+
authorizedFilter, err := prepared.CompileToSQL(regosql.ConvertConfig{
35+
VariableConverter: regosql.TemplateConverter(),
36+
})
3337
if err != nil {
3438
return nil, xerrors.Errorf("compile authorized filter: %w", err)
3539
}

coderd/rbac/regosql/alwaysfalse.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package regosql
2+
3+
import (
4+
"github.com/coder/coder/coderd/rbac/regosql/sqltypes"
5+
"github.com/open-policy-agent/opa/ast"
6+
)
7+
8+
var _ sqltypes.Node = alwaysFalse{}
9+
var _ sqltypes.VariableMatcher = alwaysFalse{}
10+
11+
type alwaysFalse struct {
12+
Matcher sqltypes.VariableMatcher
13+
14+
InnerNode sqltypes.Node
15+
}
16+
17+
func AlwaysFalse(m sqltypes.VariableMatcher) alwaysFalse {
18+
return alwaysFalse{
19+
Matcher: m,
20+
}
21+
}
22+
23+
func (alwaysFalse) UseAs() sqltypes.Node { return sqltypes.AstBoolean{} }
24+
func (g alwaysFalse) ConvertVariable(rego ast.Ref) (sqltypes.Node, bool) {
25+
n, ok := g.Matcher.ConvertVariable(rego)
26+
if ok {
27+
return alwaysFalse{
28+
Matcher: g.Matcher,
29+
InnerNode: n,
30+
}, true
31+
}
32+
33+
return nil, false
34+
}
35+
36+
func (g alwaysFalse) SQLString(_ *sqltypes.SQLGenerator) string {
37+
return "false"
38+
}
39+
40+
func (g alwaysFalse) ContainsSQL(_ *sqltypes.SQLGenerator, _ sqltypes.Node) (string, error) {
41+
return "false", nil
42+
}
43+
44+
func (g alwaysFalse) EqualsSQLString(_ *sqltypes.SQLGenerator, not bool, _ sqltypes.Node) (string, error) {
45+
return "false", nil
46+
}

coderd/rbac/regosql/configs.go

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ package regosql
22

33
import "github.com/coder/coder/coderd/rbac/regosql/sqltypes"
44

5+
// For the templates table
6+
func TemplateConverter() *sqltypes.VariableConverter {
7+
matcher := sqltypes.NewVariableConverter().RegisterMatcher(
8+
// Basic strings
9+
AlwaysFalse(sqltypes.StringVarMatcher("organization_id :: text", []string{"input", "object", "org_owner"})),
10+
sqltypes.StringVarMatcher("owner_id :: text", []string{"input", "object", "owner"}),
11+
)
12+
matcher.RegisterMatcher(
13+
ACLGroupMatcher(matcher, "group_acl", []string{"input", "object", "acl_group_list"}),
14+
ACLGroupMatcher(matcher, "user_acl", []string{"input", "object", "acl_user_list"}),
15+
)
16+
return matcher
17+
}
18+
519
// NoACLConverter should be used when the target SQL table does not contain
620
// group or user ACL columns.
721
func NoACLConverter() *sqltypes.VariableConverter {
@@ -10,11 +24,10 @@ func NoACLConverter() *sqltypes.VariableConverter {
1024
sqltypes.StringVarMatcher("organization_id :: text", []string{"input", "object", "org_owner"}),
1125
sqltypes.StringVarMatcher("owner_id :: text", []string{"input", "object", "owner"}),
1226
)
13-
aclGroups := aclGroupMatchers(matcher)
14-
for i := range aclGroups {
15-
// Disable acl groups
16-
matcher.RegisterMatcher(aclGroups[i].Disable())
17-
}
27+
matcher.RegisterMatcher(
28+
AlwaysFalse(ACLGroupMatcher(matcher, "group_acl", []string{"input", "object", "acl_group_list"})),
29+
AlwaysFalse(ACLGroupMatcher(matcher, "user_acl", []string{"input", "object", "acl_user_list"})),
30+
)
1831

1932
return matcher
2033
}
@@ -25,17 +38,10 @@ func DefaultVariableConverter() *sqltypes.VariableConverter {
2538
sqltypes.StringVarMatcher("organization_id :: text", []string{"input", "object", "org_owner"}),
2639
sqltypes.StringVarMatcher("owner_id :: text", []string{"input", "object", "owner"}),
2740
)
28-
aclGroups := aclGroupMatchers(matcher)
29-
for i := range aclGroups {
30-
matcher.RegisterMatcher(aclGroups[i])
31-
}
41+
matcher.RegisterMatcher(
42+
ACLGroupMatcher(matcher, "group_acl", []string{"input", "object", "acl_group_list"}),
43+
ACLGroupMatcher(matcher, "user_acl", []string{"input", "object", "acl_user_list"}),
44+
)
3245

3346
return matcher
3447
}
35-
36-
func aclGroupMatchers(c *sqltypes.VariableConverter) []ACLGroupVar {
37-
return []ACLGroupVar{
38-
ACLGroupMatcher(c, "group_acl", []string{"input", "object", "acl_group_list"}),
39-
ACLGroupMatcher(c, "user_acl", []string{"input", "object", "acl_user_list"}),
40-
}
41-
}

coderd/templates.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -310,25 +310,27 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
310310
func (api *API) templatesByOrganization(rw http.ResponseWriter, r *http.Request) {
311311
ctx := r.Context()
312312
organization := httpmw.OrganizationParam(r)
313-
templates, err := api.Database.GetTemplatesWithFilter(ctx, database.GetTemplatesWithFilterParams{
314-
OrganizationID: organization.ID,
315-
})
316-
if errors.Is(err, sql.ErrNoRows) {
317-
err = nil
318-
}
313+
314+
prepared, err := api.HTTPAuth.AuthorizeSQLFilter(r, rbac.ActionRead, rbac.ResourceTemplate.Type)
319315
if err != nil {
320316
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
321-
Message: "Internal error fetching templates in organization.",
317+
Message: "Internal error preparing sql filter.",
322318
Detail: err.Error(),
323319
})
324320
return
325321
}
326322

327323
// Filter templates based on rbac permissions
328-
templates, err = AuthorizeFilter(api.HTTPAuth, r, rbac.ActionRead, templates)
324+
templates, err := api.Database.GetAuthorizedTemplates(ctx, database.GetTemplatesWithFilterParams{
325+
OrganizationID: organization.ID,
326+
}, prepared)
327+
if errors.Is(err, sql.ErrNoRows) {
328+
err = nil
329+
}
330+
329331
if err != nil {
330332
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
331-
Message: "Internal error fetching templates.",
333+
Message: "Internal error fetching templates in organization.",
332334
Detail: err.Error(),
333335
})
334336
return

coderd/templates_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/stretchr/testify/require"
1212

1313
"cdr.dev/slog/sloggers/slogtest"
14-
1514
"github.com/coder/coder/agent"
1615
"github.com/coder/coder/coderd/audit"
1716
"github.com/coder/coder/coderd/coderdtest"

enterprise/coderd/templates_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ func TestUpdateTemplateACL(t *testing.T) {
757757
// This is a full rbac test of many of the common role combinations.
758758
func TestTemplateAccess(t *testing.T) {
759759
t.Parallel()
760-
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
760+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong*5)
761761
t.Cleanup(cancel)
762762

763763
ownerClient := coderdenttest.New(t, nil)

0 commit comments

Comments
 (0)