Skip to content

Commit

Permalink
sql: support ALTER DEFAULT PRIVILEGES IN SCHEMA
Browse files Browse the repository at this point in the history
Release note (sql change):
Support ALTER DEFAULT PRIVILEGES IN SCHEMA <schemas...>
Users can now in addition to specifying default privileges globally
(within a database), specify default privileges in a specific schema.

When creating an object that has default privileges specified at
the database (global) and at the schema level, the union of the
default privileges are taken.
  • Loading branch information
RichardJCai committed Dec 15, 2021
1 parent a7e903b commit e80372b
Show file tree
Hide file tree
Showing 36 changed files with 1,527 additions and 599 deletions.
1 change: 1 addition & 0 deletions docs/generated/eventlog.md
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,7 @@ An event of type `alter_default_privileges` is recorded when default privileges
| `DatabaseName` | The name of the affected database. | yes |
| `RoleName` | Either role_name should be populated or for_all_roles should be true. The role having its default privileges altered. | yes |
| `ForAllRoles` | Identifies if FOR ALL ROLES is used. | no |
| `SchemaName` | The name of the affected schema. | yes |


#### Common fields
Expand Down
4 changes: 3 additions & 1 deletion pkg/ccl/backupccl/restore_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -2639,7 +2639,9 @@ func getRestorePrivilegesForTableOrSchema(

// TODO(dt): Make this more configurable.
immutableDefaultPrivileges := parentDB.GetDefaultPrivilegeDescriptor()
updatedPrivileges = immutableDefaultPrivileges.CreatePrivilegesFromDefaultPrivileges(
updatedPrivileges = catprivilege.CreatePrivilegesFromDefaultPrivileges(
immutableDefaultPrivileges,
nil, /* schemaDefaultPrivilegeDescriptor */
parentDB.GetID(), user, tree.Tables, parentDB.GetPrivileges())
}
return updatedPrivileges, nil
Expand Down
127 changes: 118 additions & 9 deletions pkg/sql/alter_default_privileges.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/catalog/catprivilege"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/dbdesc"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/schemadesc"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/sql/privilege"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented"
"github.com/cockroachdb/cockroach/pkg/util/log/eventpb"
"github.com/cockroachdb/errors"
)

var targetObjectToPrivilegeObject = map[tree.AlterDefaultPrivilegesTargetObject]privilege.ObjectType{
Expand All @@ -36,7 +37,8 @@ var targetObjectToPrivilegeObject = map[tree.AlterDefaultPrivilegesTargetObject]
type alterDefaultPrivilegesNode struct {
n *tree.AlterDefaultPrivileges

dbDesc *dbdesc.Mutable
dbDesc *dbdesc.Mutable
schemaDescs []*schemadesc.Mutable
}

func (n *alterDefaultPrivilegesNode) Next(runParams) (bool, error) { return false, nil }
Expand Down Expand Up @@ -64,15 +66,31 @@ func (p *planner) alterDefaultPrivileges(
return nil, err
}

if len(n.Schemas) > 0 {
return nil, unimplemented.NewWithIssue(
67376, "ALTER DEFAULT PRIVILEGES IN SCHEMA not implemented",
objectType := n.Grant.Target
if !n.IsGrant {
objectType = n.Revoke.Target
}

if len(n.Schemas) > 0 && objectType == tree.Schemas {
return nil, pgerror.WithCandidateCode(errors.New(
"cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS"),
pgcode.InvalidGrantOperation,
)
}

var schemaDescs []*schemadesc.Mutable
for _, sc := range n.Schemas {
schemaDesc, err := p.Descriptors().GetMutableSchemaByName(ctx, p.txn, dbDesc, sc.Schema(), tree.SchemaLookupFlags{Required: true})
if err != nil {
return nil, err
}
schemaDescs = append(schemaDescs, schemaDesc.(*schemadesc.Mutable))
}

return &alterDefaultPrivilegesNode{
n: n,
dbDesc: dbDesc,
n: n,
dbDesc: dbDesc,
schemaDescs: schemaDescs,
}, err
}

Expand Down Expand Up @@ -139,8 +157,99 @@ func (n *alterDefaultPrivilegesNode) startExec(params runParams) error {
return err
}

if len(n.schemaDescs) == 0 {
return n.alterDefaultPrivilegesForDatabase(params, targetRoles, objectType, grantees, privileges, grantOption)
}
return n.alterDefaultPrivilegesForSchemas(params, targetRoles, objectType, grantees, privileges, grantOption)
}

func (n *alterDefaultPrivilegesNode) alterDefaultPrivilegesForSchemas(
params runParams,
targetRoles []security.SQLUsername,
objectType tree.AlterDefaultPrivilegesTargetObject,
grantees tree.RoleSpecList,
privileges privilege.List,
grantOption bool,
) error {
var events []eventLogEntry
for _, schemaDesc := range n.schemaDescs {
if schemaDesc.GetDefaultPrivileges() == nil {
schemaDesc.SetDefaultPrivilegeDescriptor(catprivilege.MakeDefaultPrivilegeDescriptor(descpb.DefaultPrivilegeDescriptor_SCHEMA))
}

defaultPrivs := schemaDesc.GetMutableDefaultPrivilegeDescriptor()

var roles []descpb.DefaultPrivilegesRole
if n.n.ForAllRoles {
roles = append(roles, descpb.DefaultPrivilegesRole{
ForAllRoles: true,
})
} else {
roles = make([]descpb.DefaultPrivilegesRole, len(targetRoles))
for i, role := range targetRoles {
roles[i] = descpb.DefaultPrivilegesRole{
Role: role,
}
}
}

granteeSQLUsernames, err := grantees.ToSQLUsernames(params.SessionData(), security.UsernameValidation)
if err != nil {
return err
}
for _, role := range roles {
if n.n.IsGrant {
defaultPrivs.GrantDefaultPrivileges(
role, privileges, granteeSQLUsernames, objectType, grantOption,
)
} else {
defaultPrivs.RevokeDefaultPrivileges(
role, privileges, granteeSQLUsernames, objectType, grantOption,
)
}

eventDetails := eventpb.CommonSQLPrivilegeEventDetails{}
if n.n.IsGrant {
eventDetails.GrantedPrivileges = privileges.SortedNames()
} else {
eventDetails.RevokedPrivileges = privileges.SortedNames()
}
event := eventpb.AlterDefaultPrivileges{
CommonSQLPrivilegeEventDetails: eventDetails,
SchemaName: schemaDesc.GetName(),
}
if n.n.ForAllRoles {
event.ForAllRoles = true
} else {
event.RoleName = role.Role.Normalized()
}

events = append(events, eventLogEntry{
targetID: int32(n.dbDesc.GetID()),
event: &event,
})

if err := params.p.writeSchemaDescChange(
params.ctx, schemaDesc, tree.AsStringWithFQNames(n.n, params.Ann()),
); err != nil {
return err
}
}
}

return params.p.logEvents(params.ctx, events...)
}

func (n *alterDefaultPrivilegesNode) alterDefaultPrivilegesForDatabase(
params runParams,
targetRoles []security.SQLUsername,
objectType tree.AlterDefaultPrivilegesTargetObject,
grantees tree.RoleSpecList,
privileges privilege.List,
grantOption bool,
) error {
if n.dbDesc.GetDefaultPrivileges() == nil {
n.dbDesc.SetDefaultPrivilegeDescriptor(catprivilege.MakeNewDefaultPrivilegeDescriptor())
n.dbDesc.SetDefaultPrivilegeDescriptor(catprivilege.MakeDefaultPrivilegeDescriptor(descpb.DefaultPrivilegeDescriptor_DATABASE))
}

defaultPrivs := n.dbDesc.GetMutableDefaultPrivilegeDescriptor()
Expand All @@ -160,7 +269,7 @@ func (n *alterDefaultPrivilegesNode) startExec(params runParams) error {
}

var events []eventLogEntry
granteeSQLUsernames, err = grantees.ToSQLUsernames(params.SessionData(), security.UsernameValidation)
granteeSQLUsernames, err := grantees.ToSQLUsernames(params.SessionData(), security.UsernameValidation)
if err != nil {
return err
}
Expand Down
1 change: 0 additions & 1 deletion pkg/sql/catalog/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ go_library(
"//pkg/keys",
"//pkg/kv",
"//pkg/roachpb:with-mocks",
"//pkg/security",
"//pkg/server/telemetry",
"//pkg/sql/catalog/descpb",
"//pkg/sql/pgwire/pgcode",
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/catalog/catprivilege/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ go_test(
"//pkg/sql/privilege",
"//pkg/sql/sem/tree",
"//pkg/util/leaktest",
"@com_github_stretchr_testify//require",
],
)
Loading

0 comments on commit e80372b

Please sign in to comment.