-
Notifications
You must be signed in to change notification settings - Fork 128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add some patterns support to blacklist [T660] #226
Add some patterns support to blacklist [T660] #226
Conversation
|
acra-censor/acra-censor_test.go
Outdated
|
||
func TestBlacklistPatterns(t *testing.T) { | ||
//test %%SELECT%% pattern | ||
testBlacklistPattern0(t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better to use meaningful names for functions:
- testBlacklistSelectPattern
- testBlacklistColumnPattern
- testBlacklistWherePattern
- testBlacklistValuePattern
acra-censor/acra-censor_test.go
Outdated
//Queries that should be blocked by first pattern have indexes: [0 .. 12] (all select queries) | ||
for i, query := range queries { | ||
err := censor.HandleQuery(query) | ||
if i <= 12 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const SelectQueryCount = 12
for ....
if i < SelectQueryCount {}
....
It is less readable when we need to find comment some line above that explain what the number mean in if
clause
acra-censor/acra-censor_test.go
Outdated
testBlacklistPattern3(t) | ||
|
||
} | ||
func testBlacklistPattern0(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be good to add some general comment about whole test case like "test that all 'select' queries will be blocked by blacklist handler". after that future reader will understand whole logic and know what expect
or use verbose function names :)
acra-censor/acra-censor_test.go
Outdated
queries := []string{ | ||
"SELECT A", | ||
"SELECT A, B", | ||
"SELECT A, B, C", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better to use two arrays of positive and negative values to check them in a loop.
in a future when someone will need to add some special value to check he will need just to add new query to correct array
or copy-paste one more if
block and increase code size without need
plus it's more readable when you see
for _, query := range AcceptableQueries {
// do something
if err != nil {
t.Log("unexpected error")
}
}
for _, blockableQuery := range BlockableQueries {
// do something
if err == nil {
t.Log("we expect error")
}
}
acra-censor/acra-censor_test.go
Outdated
t.Fatal(err) | ||
} | ||
queries := []string{ | ||
"SELECT a, b, c FROM x WHERE a = 'someValue'", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add cases with two/three conditions: a='some value' and b=2 or c between 20 and 30
if err != nil { | ||
log.WithField(logging.FieldKeyEventCode, logging.EventCodeErrorCensorQueryParseError).WithError(err).Errorln("Can't parse query to add rule to blacklist handler") | ||
return ErrQuerySyntaxError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this type of error specially handled on acra-censor level to ignore errors when we can't parse sql queries
patternDetected := false | ||
matchOccurred := false | ||
patternDetected, matchOccurred = handleSelectPattern(queryNodes, patternNodes) | ||
if patternDetected { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not if patternDetected && matchOccurred
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and for what we use patternDetected
? why not just check that matchOccurred
?
func handleSelectColumnPattern(queryNodes, patternNodes []sqlparser.SQLNode) (patternDetected bool, matchOccurred bool) { | ||
var emptySelect *sqlparser.Select | ||
if reflect.TypeOf(queryNodes[0]) == reflect.TypeOf(emptySelect) && reflect.TypeOf(patternNodes[0]) == reflect.TypeOf(emptySelect) { | ||
if strings.Contains(sqlparser.String(patternNodes[0].(*sqlparser.Select).SelectExprs), ColumnConfigPlaceholderReplacer) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we somehow to remember result of it and don't check it always? for example on config load and remembering patterns that contains such pattern and check only them with this filter?
var emptySelect *sqlparser.Select | ||
if reflect.TypeOf(queryNodes[0]) == reflect.TypeOf(emptySelect) && reflect.TypeOf(patternNodes[0]) == reflect.TypeOf(emptySelect) { | ||
if strings.Contains(sqlparser.String(patternNodes[0].(*sqlparser.Select).SelectExprs), ColumnConfigPlaceholderReplacer) { | ||
if len(patternNodes[0].(*sqlparser.Select).SelectExprs) == len(queryNodes[0].(*sqlparser.Select).SelectExprs) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how we check that places of pattern %%COLUMN%%
the same as in query? how it handle cases like:
pattern: select a, %%COLUMN%% from table
query: select b, blabla from table
?
We doesn't calculate count of %%column%% pattern to compare it with columns count in query
//handle SELECT a, b from t %%WHERE%% pattern | ||
func handleSelectWherePattern(queryNodes, patternNodes []sqlparser.SQLNode) (patternDetected bool, matchOccurred bool) { | ||
var emptySelect *sqlparser.Select | ||
if reflect.TypeOf(queryNodes[0]) == reflect.TypeOf(emptySelect) && reflect.TypeOf(patternNodes[0]) == reflect.TypeOf(emptySelect) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we use this check > 1 times. what about to add some helper like func isSelectQuery(node sqlparser.SQLNode)
and then use:
if isSelectQuery(queryNodes[0]) && isSelectQuery(patternNodes[0])
? it's more readable and we encapsulate logic of detecting query type
|
@@ -160,153 +157,208 @@ func (handler *BlacklistHandler) handleParenTables(statement *sqlparser.ParenTab | |||
return nil | |||
} | |||
|
|||
// Reset blacklist rules | |||
func (handler *BlacklistHandler) Reset() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed comment :(
} | ||
|
||
// Release / reset blacklist rules |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed comment :(
func (handler *BlacklistHandler) Release() { | ||
handler.Reset() | ||
} | ||
|
||
// AddQueries adds queries to the list that should be blacklisted |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed comment :(
Please don't remove |
} | ||
|
||
// NewBlacklistHandler creates new blacklist handler | ||
func NewBlacklistHandler() *BlacklistHandler { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still removed
if index == 0 || reflect.DeepEqual(patternNode, queryNodes[index]) { | ||
continue | ||
} | ||
if patternNodeColName, ok := patternNode.(*sqlparser.ColName); ok && patternNodeColName != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if type of node in query != type of node in pattern and it's not ColName? Can we check that they both has same type and then check value of .Name
?
if queryWhereNode, ok := queryNodes[index].(*sqlparser.Where); ok && queryWhereNode != nil { | ||
queryWhereDetected = true | ||
} | ||
if patternWhereDetected == queryWhereDetected && patternWhereDetected { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true == true && true ?)
better to leave only patternWhereDetected && queryWhereDetected
, because it's true only when both are true
@@ -88,9 +89,10 @@ func (handler *BlacklistHandler) CheckQuery(query string) (bool, error) { | |||
} | |||
//Check patterns | |||
if len(handler.patterns) != 0 { | |||
//fmt.Println("here") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
git add -p acra-censor/handlers/blacklist_handler.go
and you can not include this :)
acra-censor/acra-censor_test.go
Outdated
"SELECT * FROM company WHERE AGE NOT IN ( 25, 27 )", | ||
"SELECT * FROM company WHERE AGE > (SELECT AGE FROM COMPANY WHERE SALARY > 65000)", | ||
"SELECT AGE FROM company WHERE EXISTS (SELECT AGE FROM company WHERE SALARY > 65000)", | ||
"SELECT age FROM company11 WHERE EXISTS (SELECT AGE FROM company WHERE SALARY > 65000)", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this query blockable too? company
!= company11
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because internal query inside EXISTS block try to access to 'company'
queryTables = querySelectStatement.From | ||
} | ||
} | ||
if patternStarDetected { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we move this check after walking through patternNodes and write if !patternStarDetected{ return false}
to avoid processing second loop?
if querySelectStatement, ok := queryNode.(*sqlparser.Select); ok && querySelectStatement != nil { | ||
queryTables = querySelectStatement.From | ||
if queryWhereNode, ok := queryNodes[index+queryNodeOffset].(*sqlparser.Where); ok && queryWhereNode != nil { | ||
queryWhereDetected = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we return true
here and false
in else
block and don't check queryWhereDetected && partternWhereDetected
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if nodes are not both *sqlparser.Where?
starDetected := false | ||
sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) { | ||
if _, ok := node.(*sqlparser.StarExpr); ok { | ||
starDetected = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we stop walking here somehow? return error or false maybe
} | ||
} | ||
} | ||
//func (handler *WhitelistHandler) RemoveRules(rules []string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if it's commented, remove it?
@@ -10,15 +10,13 @@ import ( | |||
log "github.com/sirupsen/logrus" | |||
) | |||
|
|||
// WhitelistHandler shows handler structure | |||
type WhitelistHandler struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
type WhitelistHandler struct { | ||
queries map[string]bool | ||
tables map[string]bool | ||
rules []string | ||
logger *log.Entry | ||
} | ||
|
||
// NewWhitelistHandler creates new white handler | ||
func NewWhitelistHandler() *WhitelistHandler { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
@@ -27,8 +25,6 @@ func NewWhitelistHandler() *WhitelistHandler { | |||
return handler | |||
} | |||
|
|||
// CheckQuery checks each query, returns false and error if query is not in a white list or | |||
// if query tries to access to non-whitelisted table | |||
func (handler *WhitelistHandler) CheckQuery(query string) (bool, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
@@ -191,48 +187,41 @@ func (handler *WhitelistHandler) handleParenTables(statement *sqlparser.ParenTab | |||
return nil | |||
} | |||
|
|||
// Reset whitelist rules | |||
func (handler *WhitelistHandler) Reset() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
func (handler *WhitelistHandler) Reset() { | ||
handler.queries = make(map[string]bool) | ||
handler.tables = make(map[string]bool) | ||
handler.rules = nil | ||
} | ||
|
||
// Release / reset whitelist rules | ||
func (handler *WhitelistHandler) Release() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
func (handler *WhitelistHandler) Release() { | ||
handler.Reset() | ||
} | ||
|
||
// AddQueries adds queries to the list that should be whitelisted | ||
func (handler *WhitelistHandler) AddQueries(queries []string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
func (handler *WhitelistHandler) AddQueries(queries []string) { | ||
for _, query := range queries { | ||
handler.queries[query] = true | ||
} | ||
} | ||
|
||
// RemoveQueries removes queries from the list that should be whitelisted | ||
func (handler *WhitelistHandler) RemoveQueries(queries []string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
func (handler *WhitelistHandler) RemoveQueries(queries []string) { | ||
for _, query := range queries { | ||
delete(handler.queries, query) | ||
} | ||
} | ||
|
||
// AddTables adds tables that should be whitelisted | ||
func (handler *WhitelistHandler) AddTables(tableNames []string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
func (handler *WhitelistHandler) AddTables(tableNames []string) { | ||
for _, tableName := range tableNames { | ||
handler.tables[tableName] = true | ||
} | ||
} | ||
|
||
// RemoveTables removes whitelisted tables | ||
func (handler *WhitelistHandler) RemoveTables(tableNames []string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
func (handler *WhitelistHandler) RemoveTables(tableNames []string) { | ||
for _, tableName := range tableNames { | ||
delete(handler.tables, tableName) | ||
} | ||
} | ||
|
||
// AddRules adds rules that should be whitelisted | ||
func (handler *WhitelistHandler) AddRules(rules []string) error { | ||
func (handler *WhitelistHandler) AddPatterns(rules []string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
t.Fatal(err) | ||
} | ||
} | ||
//whitelistHandler.RemovePatterns(testSecurityRules) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is it commented?
) | ||
|
||
// BlacklistHandler shows handler structure | ||
type BlacklistHandler struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment missing
handler.logger = log.WithField("handler", "blacklist") | ||
return handler | ||
} | ||
|
||
// CheckQuery checks each query, returns false and error if query is blacklisted or | ||
// if query tries to access to forbidden table | ||
//CheckQuery checks input query |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new comment doesn't look very helpful, however old one was.
maybe update old comment?
@@ -105,8 +103,9 @@ func (handler *BlacklistHandler) CheckQuery(query string) (bool, error) { | |||
func (handler *BlacklistHandler) handleAliasedTables(statement *sqlparser.AliasedTableExpr) error { | |||
if handler.tables[sqlparser.String(statement.Expr)] { | |||
return ErrAccessToForbiddenTableBlacklist | |||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
golint has a rule: if method ends on
if
return
else
return
it should be changed to (remove else)
if
return
return
I think that we can now merge (into acracensor branch), and more carefully look for a golint when will merge into master |
Merge it!
…On Wed, Aug 1, 2018 at 19:37 Artem Storozhuk ***@***.***> wrote:
I think that we can now merge (into acracensor branch), and more carefully
look for a golint when will merge into master
—
You are receiving this because your review was requested.
Reply to this email directly, view it on GitHub
<#226 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACvp4Do_H0dPt-QeBhFH343o2w2k0sEbks5uMdk7gaJpZM4VlHtG>
.
|
I added some stubs (commented some places in code) to whitelist workflow - would like to know from reviewers if blacklist now will work as expected