Skip to content

Commit

Permalink
[breaking] Remove the ALL grant (#322)
Browse files Browse the repository at this point in the history
<!-- Feel free to delete comments as you fill this in -->

<!-- summary of changes -->
Removing the ALL grant. See #318. I will follow up with more documentation in a separate PR

## Test Plan
<!-- detail ways in which this PR has been tested or needs to be tested -->
* [X] acceptance tests


## References
<!-- issues documentation links, etc  -->

*
  • Loading branch information
Eduardo Lopez committed Dec 7, 2020
1 parent 01f2d61 commit dc6dc13
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 146 deletions.
2 changes: 1 addition & 1 deletion pkg/resources/account_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
)

var validAccountPrivileges = newPrivilegeSet(
var validAccountPrivileges = NewPrivilegeSet(
privilegeCreateRole,
privilegeCreateUser,
privilegeCreateWarehouse,
Expand Down
3 changes: 1 addition & 2 deletions pkg/resources/database_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

var ValidDatabasePrivileges = newPrivilegeSet(
privilegeAll,
var ValidDatabasePrivileges = NewPrivilegeSet(
privilegeCreateSchema,
privilegeImportedPrivileges,
privilegeModify,
Expand Down
74 changes: 7 additions & 67 deletions pkg/resources/grant_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,63 +65,6 @@ type grantID struct {
GrantOption bool
}

// Because none of the grants currently have a privilege of "ALL", rather they explicitly say
// each privilege for each database_schema pair, we want to collapse them into one grant that has
// the privilege of "ALL". filterAllGrants allows us to filter the grants and reassign their privilege
// to "ALL".
func filterALLGrants(grantList []*grant, validPrivs privilegeSet) []*grant {
// We only filter if ALL is in validPrivs.
_, ok := validPrivs[privilegeAll]
if !ok {
return grantList
}

groupedByRole := map[grant]privilegeSet{}
for _, g := range grantList {
id := grant{
GrantName: g.GrantName,
GranteeType: g.GranteeType,
GranteeName: g.GranteeName,
GrantOption: g.GrantOption,
}
if _, ok := groupedByRole[id]; !ok {
groupedByRole[id] = privilegeSet{}
}
groupedByRole[id].addString(g.Privilege)
}
for databaseSchemaRole, privs := range groupedByRole {
if !privs.ALLPrivsPresent(validPrivs) {
delete(groupedByRole, databaseSchemaRole)
}
}
filteredGrants := []*grant{}

// Roles with the "ALL" privilege
for databaseSchemaRole := range groupedByRole {
filteredGrants = append(filteredGrants, &grant{
GrantName: databaseSchemaRole.GrantName,
Privilege: privilegeAll.string(),
GranteeType: databaseSchemaRole.GranteeType,
GranteeName: databaseSchemaRole.GranteeName,
})
}

for _, g := range grantList {
id := grant{
GrantName: g.GrantName,
GranteeType: g.GranteeType,
GranteeName: g.GranteeName,
GrantOption: g.GrantOption,
}
// Already added it with the "ALL" privilege, so skip
if _, ok := groupedByRole[id]; ok {
continue
}
filteredGrants = append(filteredGrants, g)
}
return filteredGrants
}

// String() takes in a grantID object and returns a pipe-delimited string:
// resourceName|schemaName|ObjectName|Privilege|GrantOption
func (gi *grantID) String() (string, error) {
Expand Down Expand Up @@ -205,7 +148,7 @@ func readGenericGrant(
schema map[string]*schema.Schema,
builder snowflake.GrantBuilder,
futureObjects bool,
validPrivileges privilegeSet) error {
validPrivileges PrivilegeSet) error {
db := meta.(*sql.DB)
var grants []*grant
var err error
Expand Down Expand Up @@ -235,12 +178,9 @@ func readGenericGrant(
}
}

// We re-aggregate grants that would be equivalent to the "ALL" grant
grants = filterALLGrants(grants, validPrivileges)

// Map of roles to privileges
rolePrivileges := map[string]privilegeSet{}
sharePrivileges := map[string]privilegeSet{}
rolePrivileges := map[string]PrivilegeSet{}
sharePrivileges := map[string]PrivilegeSet{}

// List of all grants for each schema_database
for _, grant := range grants {
Expand All @@ -251,7 +191,7 @@ func readGenericGrant(
privileges, ok := rolePrivileges[roleName]
if !ok {
// If not there, create an empty set
privileges = privilegeSet{}
privileges = PrivilegeSet{}
}
// Add privilege to the set but consider valid privileges only
// for VIEW in ReadViewGrant
Expand All @@ -271,7 +211,7 @@ func readGenericGrant(
privileges, ok := sharePrivileges[granteeNameStrippedAccount]
if !ok {
// If not there, create an empty set
privileges = privilegeSet{}
privileges = PrivilegeSet{}
}
// Add privilege to the set
privileges.addString(grant.Privilege)
Expand All @@ -286,15 +226,15 @@ func readGenericGrant(
// Now see which roles have our privilege
for roleName, privileges := range rolePrivileges {
// Where priv is not all so it should match exactly
if privileges.hasString(priv) || privileges.ALLPrivsPresent(validPrivileges) {
if privileges.hasString(priv) {
roles = append(roles, roleName)
}
}

// Now see which shares have our privilege
for shareName, privileges := range sharePrivileges {
// Where priv is not all so it should match exactly
if privileges.hasString(priv) || privileges.ALLPrivsPresent(validPrivileges) {
if privileges.hasString(priv) {
shares = append(shares, shareName)
}
}
Expand Down
3 changes: 1 addition & 2 deletions pkg/resources/integration_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

var validIntegrationPrivileges = newPrivilegeSet(
privilegeAll,
var validIntegrationPrivileges = NewPrivilegeSet(
privilegeUsage,
privilegeOwnership,
)
Expand Down
111 changes: 49 additions & 62 deletions pkg/resources/privileges.go
Original file line number Diff line number Diff line change
@@ -1,90 +1,77 @@
package resources

type privilege string
type Privilege string

func (p privilege) string() string {
func (p Privilege) String() string {
return string(p)
}

const (
privilegeAll privilege = "ALL"
privilegeSelect privilege = "SELECT"
privilegeInsert privilege = "INSERT"
privilegeUpdate privilege = "UPDATE"
privilegeDelete privilege = "DELETE"
privilegeTruncate privilege = "TRUNCATE"
privilegeReferences privilege = "REFERENCES"
privilegeCreateSchema privilege = "CREATE SCHEMA"
privilegeImportedPrivileges privilege = "IMPORTED PRIVILEGES"
privilegeModify privilege = "MODIFY"
privilegeOperate privilege = "OPERATE"
privilegeMonitor privilege = "MONITOR"
privilegeOwnership privilege = "OWNERSHIP"
privilegeRead privilege = "READ"
privilegeReferenceUsage privilege = "REFERENCE_USAGE"
privilegeUsage privilege = "USAGE"
privilegeWrite privilege = "WRITE"
privilegeCreateTable privilege = "CREATE TABLE"
privilegeCreateView privilege = "CREATE VIEW"
privilegeCreateFileFormat privilege = "CREATE FILE FORMAT"
privilegeCreateStage privilege = "CREATE STAGE"
privilegeCreatePipe privilege = "CREATE PIPE"
privilegeCreateStream privilege = "CREATE STREAM"
privilegeCreateTask privilege = "CREATE TASK"
privilegeCreateSequence privilege = "CREATE SEQUENCE"
privilegeCreateFunction privilege = "CREATE FUNCTION"
privilegeCreateProcedure privilege = "CREATE PROCEDURE"
privilegeCreateExternalTable privilege = "CREATE EXTERNAL TABLE"
privilegeCreateMaterializedView privilege = "CREATE MATERIALIZED VIEW"
privilegeCreateTemporaryTable privilege = "CREATE TEMPORARY TABLE"
privilegeCreateMaskingPolicy privilege = "CREATE MASKING POLICY"
privilegeSelect Privilege = "SELECT"
privilegeInsert Privilege = "INSERT"
privilegeUpdate Privilege = "UPDATE"
privilegeDelete Privilege = "DELETE"
privilegeTruncate Privilege = "TRUNCATE"
privilegeReferences Privilege = "REFERENCES"
privilegeCreateSchema Privilege = "CREATE SCHEMA"
privilegeImportedPrivileges Privilege = "IMPORTED PRIVILEGES"
privilegeModify Privilege = "MODIFY"
privilegeOperate Privilege = "OPERATE"
privilegeMonitor Privilege = "MONITOR"
privilegeOwnership Privilege = "OWNERSHIP"
privilegeRead Privilege = "READ"
privilegeReferenceUsage Privilege = "REFERENCE_USAGE"
privilegeUsage Privilege = "USAGE"
privilegeWrite Privilege = "WRITE"
privilegeCreateTable Privilege = "CREATE TABLE"
privilegeCreateView Privilege = "CREATE VIEW"
privilegeCreateFileFormat Privilege = "CREATE FILE FORMAT"
privilegeCreateStage Privilege = "CREATE STAGE"
privilegeCreatePipe Privilege = "CREATE PIPE"
privilegeCreateStream Privilege = "CREATE STREAM"
privilegeCreateTask Privilege = "CREATE TASK"
privilegeCreateSequence Privilege = "CREATE SEQUENCE"
privilegeCreateFunction Privilege = "CREATE FUNCTION"
privilegeCreateProcedure Privilege = "CREATE PROCEDURE"
privilegeCreateExternalTable Privilege = "CREATE EXTERNAL TABLE"
privilegeCreateMaterializedView Privilege = "CREATE MATERIALIZED VIEW"
privilegeCreateTemporaryTable Privilege = "CREATE TEMPORARY TABLE"
privilegeCreateMaskingPolicy Privilege = "CREATE MASKING POLICY"

privilegeCreateRole privilege = "CREATE ROLE"
privilegeCreateUser privilege = "CREATE USER"
privilegeCreateWarehouse privilege = "CREATE WAREHOUSE"
privilegeCreateDatabase privilege = "CREATE DATABASE"
privilegeCreateIntegration privilege = "CREATE INTEGRATION"
privilegeManageGrants privilege = "MANAGE GRANTS"
privilegeMonitorUsage privilege = "MONITOR USAGE"
privilegeMonitorExecution privilege = "MONITOR EXECUTION"
privilegeExecuteTask privilege = "EXECUTE TASK"
privilegeCreateRole Privilege = "CREATE ROLE"
privilegeCreateUser Privilege = "CREATE USER"
privilegeCreateWarehouse Privilege = "CREATE WAREHOUSE"
privilegeCreateDatabase Privilege = "CREATE DATABASE"
privilegeCreateIntegration Privilege = "CREATE INTEGRATION"
privilegeManageGrants Privilege = "MANAGE GRANTS"
privilegeMonitorUsage Privilege = "MONITOR USAGE"
privilegeMonitorExecution Privilege = "MONITOR EXECUTION"
privilegeExecuteTask Privilege = "EXECUTE TASK"
)

type privilegeSet map[privilege]struct{}
type PrivilegeSet map[Privilege]struct{}

func newPrivilegeSet(privileges ...privilege) privilegeSet {
ps := privilegeSet{}
func NewPrivilegeSet(privileges ...Privilege) PrivilegeSet {
ps := PrivilegeSet{}
for _, priv := range privileges {
ps[priv] = struct{}{}
}
return ps
}

func (ps privilegeSet) toList() []string {
func (ps PrivilegeSet) toList() []string {
privs := []string{}
for p := range ps {
privs = append(privs, string(p))
}
return privs
}

func (ps privilegeSet) addString(s string) {
ps[privilege(s)] = struct{}{}
func (ps PrivilegeSet) addString(s string) {
ps[Privilege(s)] = struct{}{}
}

func (ps privilegeSet) hasString(s string) bool {
_, ok := ps[privilege(s)]
func (ps PrivilegeSet) hasString(s string) bool {
_, ok := ps[Privilege(s)]
return ok
}

func (ps privilegeSet) ALLPrivsPresent(validPrivs privilegeSet) bool {
for p := range validPrivs {
if p == privilegeAll || p == privilegeOwnership || p == privilegeCreateStream {
continue
}
if _, ok := ps[p]; !ok {
return false
}
}
return true
}
3 changes: 1 addition & 2 deletions pkg/resources/resource_monitor_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

var validResourceMonitorPrivileges = newPrivilegeSet(
privilegeAll,
var validResourceMonitorPrivileges = NewPrivilegeSet(
privilegeModify,
privilegeMonitor,
)
Expand Down
5 changes: 1 addition & 4 deletions pkg/resources/schema_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import (
"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
)

// Intentionally exclude the "ALL" alias because it is not a real privilege and
// might not interact well with this provider.
var validSchemaPrivileges = newPrivilegeSet(
privilegeAll,
var validSchemaPrivileges = NewPrivilegeSet(
privilegeModify,
privilegeMonitor,
privilegeOwnership,
Expand Down
3 changes: 1 addition & 2 deletions pkg/resources/stage_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import (
"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
)

var ValidStagePrivileges = newPrivilegeSet(
privilegeAll,
var ValidStagePrivileges = NewPrivilegeSet(
privilegeOwnership,
privilegeUsage,
// These privileges are only valid for internal stages
Expand Down
2 changes: 1 addition & 1 deletion pkg/resources/table_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
)

var validTablePrivileges = newPrivilegeSet(
var validTablePrivileges = NewPrivilegeSet(
privilegeSelect,
privilegeInsert,
privilegeUpdate,
Expand Down
2 changes: 1 addition & 1 deletion pkg/resources/view_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/chanzuckerberg/terraform-provider-snowflake/pkg/snowflake"
)

var ValidViewPrivileges = newPrivilegeSet(
var ValidViewPrivileges = NewPrivilegeSet(
privilegeSelect,
)

Expand Down
3 changes: 1 addition & 2 deletions pkg/resources/warehouse_grant.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

var validWarehousePrivileges = newPrivilegeSet(
privilegeAll,
var validWarehousePrivileges = NewPrivilegeSet(
privilegeModify,
privilegeMonitor,
privilegeOperate,
Expand Down

0 comments on commit dc6dc13

Please sign in to comment.