Skip to content

Commit

Permalink
feat(#3): Add security enforcement for PgSQL
Browse files Browse the repository at this point in the history
  • Loading branch information
borisershov committed May 31, 2024
1 parent 48853c6 commit 193bc21
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 81 deletions.
10 changes: 9 additions & 1 deletion ctx/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"os"
"time"

mysql_anonymize "github.com/nixys/nxs-data-anonymizer/modules/anonymizers/mysql"
pgsql_anonymize "github.com/nixys/nxs-data-anonymizer/modules/anonymizers/pgsql"

"github.com/nixys/nxs-data-anonymizer/ds/mysql"
"github.com/nixys/nxs-data-anonymizer/misc"
"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter"
Expand Down Expand Up @@ -134,7 +137,12 @@ func AppCtxInit() (any, error) {
c.Rules.Tables = make(map[string]relfilter.TableRules)

if misc.SecurityPolicyColumnsTypeFromString(conf.Security.Policy.Columns) == misc.SecurityPolicyColumnsRandomize {
c.Rules.RandomizeTypes = relfilter.RandomizeTypesDefault
switch args.DBType {
case DBTypeMySQL:
c.Rules.RandomizeTypes = mysql_anonymize.RandomizeTypesDefault
case DBTypePgSQL:
c.Rules.RandomizeTypes = pgsql_anonymize.RandomizeTypesDefault
}
}

for t, f := range conf.Filters {
Expand Down
4 changes: 2 additions & 2 deletions modules/anonymizers/mysql/dh.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ func rowDataGen(filter *relfilter.Filter) []byte {
out += "NULL"
} else {
switch filter.ColumnTypeGet(i) {
case relfilter.ColumnTypeString:
case columnTypeString:
out += fmt.Sprintf("'%s'", v.V)
case relfilter.ColumnTypeBinary:
case columnTypeBinary:
out += fmt.Sprintf("_binary '%s'", v.V)
default:
out += fmt.Sprintf("%s", v.V)
Expand Down
92 changes: 58 additions & 34 deletions modules/anonymizers/mysql/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,50 +42,74 @@ type securityCtx struct {
tableExceptions map[string]any
}

const (
columnTypeString relfilter.ColumnType = "string"
columnTypeNum relfilter.ColumnType = "numeric"
columnTypeBinary relfilter.ColumnType = "binary"
)

var typeKeys = map[string]relfilter.ColumnType{

// Special
"generated": relfilter.ColumnTypeNone,

// Strings
"char": relfilter.ColumnTypeString,
"varchar": relfilter.ColumnTypeString,
"tinytext": relfilter.ColumnTypeString,
"text": relfilter.ColumnTypeString,
"mediumtext": relfilter.ColumnTypeString,
"longtext": relfilter.ColumnTypeString,
"enum": relfilter.ColumnTypeString,
"set": relfilter.ColumnTypeString,
"date": relfilter.ColumnTypeString,
"datetime": relfilter.ColumnTypeString,
"timestamp": relfilter.ColumnTypeString,
"time": relfilter.ColumnTypeString,
"year": relfilter.ColumnTypeString,
"json": relfilter.ColumnTypeString,
"char": columnTypeString,
"varchar": columnTypeString,
"tinytext": columnTypeString,
"text": columnTypeString,
"mediumtext": columnTypeString,
"longtext": columnTypeString,
"enum": columnTypeString,
"set": columnTypeString,
"date": columnTypeString,
"datetime": columnTypeString,
"timestamp": columnTypeString,
"time": columnTypeString,
"year": columnTypeString,
"json": columnTypeString,

// Numeric
"bit": relfilter.ColumnTypeNum,
"bool": relfilter.ColumnTypeNum,
"boolean": relfilter.ColumnTypeNum,
"tinyint": relfilter.ColumnTypeNum,
"smallint": relfilter.ColumnTypeNum,
"mediumint": relfilter.ColumnTypeNum,
"int": relfilter.ColumnTypeNum,
"integer": relfilter.ColumnTypeNum,
"bigint": relfilter.ColumnTypeNum,
"float": relfilter.ColumnTypeNum,
"double": relfilter.ColumnTypeNum,
"double precision": relfilter.ColumnTypeNum,
"decimal": relfilter.ColumnTypeNum,
"dec": relfilter.ColumnTypeNum,
"bit": columnTypeNum,
"bool": columnTypeNum,
"boolean": columnTypeNum,
"tinyint": columnTypeNum,
"smallint": columnTypeNum,
"mediumint": columnTypeNum,
"int": columnTypeNum,
"integer": columnTypeNum,
"bigint": columnTypeNum,
"float": columnTypeNum,
"double": columnTypeNum,
"double precision": columnTypeNum,
"decimal": columnTypeNum,
"dec": columnTypeNum,

// Binary
"binary": relfilter.ColumnTypeBinary,
"varbinary": relfilter.ColumnTypeBinary,
"tinyblob": relfilter.ColumnTypeBinary,
"blob": relfilter.ColumnTypeBinary,
"mediumblob": relfilter.ColumnTypeBinary,
"longblob": relfilter.ColumnTypeBinary,
"binary": columnTypeBinary,
"varbinary": columnTypeBinary,
"tinyblob": columnTypeBinary,
"blob": columnTypeBinary,
"mediumblob": columnTypeBinary,
"longblob": columnTypeBinary,
}

var RandomizeTypesDefault = map[relfilter.ColumnType]relfilter.ColumnRule{
columnTypeBinary: {
Type: misc.ValueTypeTemplate,
Value: "cmFuZG9taXplZCBiaW5hcnkgZGF0YQo=",
Unique: false,
},
columnTypeNum: {
Type: misc.ValueTypeTemplate,
Value: "0",
Unique: false,
},
columnTypeString: {
Type: misc.ValueTypeTemplate,
Value: "randomized string data",
Unique: false,
},
}

func userCtxInit(s InitSettings) *userCtx {
Expand Down
80 changes: 76 additions & 4 deletions modules/anonymizers/pgsql/dh.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,30 @@ import (
"bytes"
"fmt"

"github.com/nixys/nxs-data-anonymizer/misc"
"github.com/nixys/nxs-data-anonymizer/modules/filters/relfilter"
)

func dhSecurityCopy(usrCtx any, deferred, token []byte) ([]byte, error) {

uctx := usrCtx.(*userCtx)

uctx.security.tmpBuf = append(uctx.security.tmpBuf, token...)

return deferred, nil
}

func dhSecurityNil(usrCtx any, deferred, token []byte) ([]byte, error) {

uctx := usrCtx.(*userCtx)

if uctx.security.isSkip == true {
return []byte{}, nil
}

return append(deferred, token...), nil
}

func dhCreateTableName(usrCtx any, deferred, token []byte) ([]byte, error) {

tname := string(bytes.TrimSpace(deferred))
Expand Down Expand Up @@ -50,12 +71,28 @@ func dhCreateTableDesc(usrCtx any, deferred, token []byte) ([]byte, error) {

func dhTableName(usrCtx any, deferred, token []byte) ([]byte, error) {

tname := bytes.TrimSpace(deferred)

uctx := usrCtx.(*userCtx)
uctx.filter.TableCreate(string(tname))

return append(deferred, token...), nil
tname := string(bytes.TrimSpace(deferred))

if !securityPolicyCheck(uctx, tname) {

// If not: table will be skipped from result dump

uctx.security.isSkip = true
uctx.security.tmpBuf = []byte{}

return []byte{}, nil
}

uctx.filter.TableCreate(tname)

d := append(uctx.security.tmpBuf, append(deferred, token...)...)

uctx.security.isSkip = false
uctx.security.tmpBuf = []byte{}

return d, nil
}

func dhFieldName(usrCtx any, deferred, token []byte) ([]byte, error) {
Expand All @@ -64,6 +101,10 @@ func dhFieldName(usrCtx any, deferred, token []byte) ([]byte, error) {

uctx := usrCtx.(*userCtx)

if uctx.security.isSkip == true {
return []byte{}, nil
}

t, b := uctx.tables[uctx.filter.TableNameGet()][string(fname)]
if b == false {
t = relfilter.ColumnTypeNone
Expand All @@ -78,6 +119,10 @@ func dhValue(usrCtx any, deferred, token []byte) ([]byte, error) {

uctx := usrCtx.(*userCtx)

if uctx.security.isSkip == true {
return []byte{}, nil
}

if bytes.Compare(deferred, []byte("\\N")) == 0 {
uctx.filter.ValueAdd(nil)
} else {
Expand All @@ -91,6 +136,10 @@ func dhValueEnd(usrCtx any, deferred, token []byte) ([]byte, error) {

uctx := usrCtx.(*userCtx)

if uctx.security.isSkip == true {
return []byte{}, nil
}

if bytes.Compare(deferred, []byte("\\N")) == 0 {
uctx.filter.ValueAdd(nil)
} else {
Expand Down Expand Up @@ -126,3 +175,26 @@ func rowDataGen(filter *relfilter.Filter) []byte {

return []byte(fmt.Sprintf("%s\n", out))
}

// SecurityPolicyCheck checks the table passes the security rules
// true: pass
// false: skip
func securityPolicyCheck(uctx *userCtx, tname string) bool {

// Continue if security policy is `skip`
if uctx.security.tablePolicy != misc.SecurityPolicyTablesSkip {
return true
}

// Check rules for specified table name
if tr := uctx.filter.TableRulesLookup(tname); tr != nil {
return true
}

// Check specified table name in exceptions
if _, b := uctx.security.tableExceptions[tname]; b == true {
return true
}

return false
}
Loading

0 comments on commit 193bc21

Please sign in to comment.