feat: Add initial AuthzQuerier implementation (#5919)

feat: Add initial AuthzQuerier implementation
- Adds package database/dbauthz that adds a database.Store implementation where each method goes through AuthZ checks
- Implements all database.Store methods on AuthzQuerier
- Updates and fixes unit tests where required
- Updates coderd initialization to use AuthzQuerier if codersdk.ExperimentAuthzQuerier is enabled
This commit is contained in:
Steven Masley
2023-02-14 08:27:06 -06:00
committed by GitHub
parent ebdfdc749d
commit 6fb8aff6d0
59 changed files with 5013 additions and 136 deletions

View File

@ -144,7 +144,9 @@ func New(ctx context.Context, options *Options) (*API, error) {
if len(options.SCIMAPIKey) != 0 {
api.AGPL.RootHandler.Route("/scim/v2", func(r chi.Router) {
r.Use(api.scimEnabledMW)
r.Use(
api.scimEnabledMW,
)
r.Post("/Users", api.scimPostUser)
r.Route("/Users", func(r chi.Router) {
r.Get("/", api.scimGetUsers)

View File

@ -6,6 +6,8 @@ import (
"testing"
"time"
"github.com/coder/coder/coderd/database/dbauthz"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/goleak"
@ -100,7 +102,9 @@ func TestEntitlements(t *testing.T) {
require.NoError(t, err)
require.False(t, entitlements.HasLicense)
coderdtest.CreateFirstUser(t, client)
_, err = api.Database.InsertLicense(context.Background(), database.InsertLicenseParams{
//nolint:gocritic // unit test
ctx := dbauthz.AsSystem(context.Background())
_, err = api.Database.InsertLicense(ctx, database.InsertLicenseParams{
UploadedAt: database.Now(),
Exp: database.Now().AddDate(1, 0, 0),
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
@ -128,7 +132,9 @@ func TestEntitlements(t *testing.T) {
require.False(t, entitlements.HasLicense)
coderdtest.CreateFirstUser(t, client)
// Valid
_, err = api.Database.InsertLicense(context.Background(), database.InsertLicenseParams{
ctx := context.Background()
//nolint:gocritic // unit test
_, err = api.Database.InsertLicense(dbauthz.AsSystem(ctx), database.InsertLicenseParams{
UploadedAt: database.Now(),
Exp: database.Now().AddDate(1, 0, 0),
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
@ -139,7 +145,8 @@ func TestEntitlements(t *testing.T) {
})
require.NoError(t, err)
// Expired
_, err = api.Database.InsertLicense(context.Background(), database.InsertLicenseParams{
//nolint:gocritic // unit test
_, err = api.Database.InsertLicense(dbauthz.AsSystem(ctx), database.InsertLicenseParams{
UploadedAt: database.Now(),
Exp: database.Now().AddDate(-1, 0, 0),
JWT: coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
@ -148,7 +155,8 @@ func TestEntitlements(t *testing.T) {
})
require.NoError(t, err)
// Invalid
_, err = api.Database.InsertLicense(context.Background(), database.InsertLicenseParams{
//nolint:gocritic // unit test
_, err = api.Database.InsertLicense(dbauthz.AsSystem(ctx), database.InsertLicenseParams{
UploadedAt: database.Now(),
Exp: database.Now().AddDate(1, 0, 0),
JWT: "invalid",

View File

@ -4,6 +4,8 @@ import (
"context"
"fmt"
"net/http"
"os"
"strings"
"testing"
"github.com/stretchr/testify/require"
@ -22,6 +24,9 @@ func TestNew(t *testing.T) {
}
func TestAuthorizeAllEndpoints(t *testing.T) {
if strings.Contains(os.Getenv("CODER_EXPERIMENTS_TEST"), string(codersdk.ExperimentAuthzQuerier)) {
t.Skip("Skipping TestAuthorizeAllEndpoints for authz_querier experiment")
}
t.Parallel()
client, _, api := coderdenttest.NewWithAPI(t, &coderdenttest.Options{
Options: &coderdtest.Options{

View File

@ -14,6 +14,7 @@ import (
agpl "github.com/coder/coder/coderd"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/dbauthz"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
)
@ -155,7 +156,8 @@ func (api *API) scimPostUser(rw http.ResponseWriter, r *http.Request) {
return
}
user, _, err := api.AGPL.CreateUser(ctx, api.Database, agpl.CreateUserRequest{
//nolint:gocritic // needed for SCIM
user, _, err := api.AGPL.CreateUser(dbauthz.AsSystem(ctx), api.Database, agpl.CreateUserRequest{
CreateUserRequest: codersdk.CreateUserRequest{
Username: sUser.UserName,
Email: email,
@ -207,7 +209,8 @@ func (api *API) scimPatchUser(rw http.ResponseWriter, r *http.Request) {
return
}
dbUser, err := api.Database.GetUserByID(ctx, uid)
//nolint:gocritic // needed for SCIM
dbUser, err := api.Database.GetUserByID(dbauthz.AsSystem(ctx), uid)
if err != nil {
_ = handlerutil.WriteError(rw, err)
return
@ -220,7 +223,8 @@ func (api *API) scimPatchUser(rw http.ResponseWriter, r *http.Request) {
status = database.UserStatusSuspended
}
_, err = api.Database.UpdateUserStatus(r.Context(), database.UpdateUserStatusParams{
//nolint:gocritic // needed for SCIM
_, err = api.Database.UpdateUserStatus(dbauthz.AsSystem(r.Context()), database.UpdateUserStatusParams{
ID: dbUser.ID,
Status: status,
UpdatedAt: database.Now(),

View File

@ -921,6 +921,10 @@ func TestTemplateAccess(t *testing.T) {
testTemplateRead := func(t *testing.T, org orgSetup, usr *codersdk.Client, read []codersdk.Template) {
found, err := usr.TemplatesByOrganization(ctx, org.Org.ID)
if len(read) == 0 && err != nil {
require.ErrorContains(t, err, "Resource not found")
return
}
require.NoError(t, err, "failed to get templates")
exp := make(map[uuid.UUID]codersdk.Template)