Support exporting SQL LOGIN and SQL TOKEN hashes

This commit is contained in:
Tobie Morgan Hitchcock 2018-10-18 01:22:44 +01:00
parent 26b138b9b0
commit 20abadf41f
7 changed files with 60 additions and 37 deletions

View file

@ -50,7 +50,12 @@ func (e *executor) executeDefineLogin(ctx context.Context, ast *sql.DefineLoginS
ast.Code = rand.New(128) ast.Code = rand.New(128)
switch len(ast.Hash) {
default:
ast.Pass = ast.Hash
case 0:
ast.Pass, _ = bcrypt.GenerateFromPassword(ast.Pass, bcrypt.DefaultCost) ast.Pass, _ = bcrypt.GenerateFromPassword(ast.Pass, bcrypt.DefaultCost)
}
switch ast.Kind { switch ast.Kind {
case sql.NAMESPACE: case sql.NAMESPACE:

View file

@ -30,6 +30,7 @@ func TestInfo(t *testing.T) {
txt := ` txt := `
USE NS test DB test; USE NS test DB test;
DEFINE LOGIN test ON NAMESPACE PASSWORD "test"; DEFINE LOGIN test ON NAMESPACE PASSWORD "test";
DEFINE LOGIN test ON NAMESPACE PASSHASH "$2a$10$mofTMm4nilzRSZuU0GyuCuAgHy2mEPeNRqHZH9ETnh.O1MBjy2PDO";
DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "test"; DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "test";
DEFINE DATABASE test; DEFINE DATABASE test;
INFO FOR NAMESPACE; INFO FOR NAMESPACE;
@ -41,24 +42,25 @@ func TestInfo(t *testing.T) {
res, err := Execute(setupKV(), txt, nil) res, err := Execute(setupKV(), txt, nil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 9) So(res, ShouldHaveLength, 10)
So(res[1].Status, ShouldEqual, "OK") So(res[1].Status, ShouldEqual, "OK")
So(res[2].Status, ShouldEqual, "OK") So(res[2].Status, ShouldEqual, "OK")
So(res[3].Status, ShouldEqual, "OK") So(res[3].Status, ShouldEqual, "OK")
So(res[4].Status, ShouldEqual, "OK") So(res[4].Status, ShouldEqual, "OK")
So(data.Consume(res[4].Result[0]).Get("login").Data(), ShouldHaveLength, 1)
So(data.Consume(res[4].Result[0]).Get("login.test").Data(), ShouldEqual, "DEFINE LOGIN test ON NAMESPACE PASSWORD ********")
So(data.Consume(res[4].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
So(data.Consume(res[4].Result[0]).Get("token.test").Data(), ShouldEqual, "DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE ********")
So(data.Consume(res[4].Result[0]).Get("database").Data(), ShouldHaveLength, 1)
So(data.Consume(res[4].Result[0]).Get("database.test").Data(), ShouldEqual, "DEFINE DATABASE test")
So(res[5].Status, ShouldEqual, "OK") So(res[5].Status, ShouldEqual, "OK")
So(data.Consume(res[5].Result[0]).Get("login").Data(), ShouldHaveLength, 1)
So(data.Consume(res[5].Result[0]).Get("login.test").Data(), ShouldEqual, `DEFINE LOGIN test ON NAMESPACE PASSHASH "$2a$10$mofTMm4nilzRSZuU0GyuCuAgHy2mEPeNRqHZH9ETnh.O1MBjy2PDO"`)
So(data.Consume(res[5].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
So(data.Consume(res[5].Result[0]).Get("token.test").Data(), ShouldEqual, `DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "test"`)
So(data.Consume(res[5].Result[0]).Get("database").Data(), ShouldHaveLength, 1)
So(data.Consume(res[5].Result[0]).Get("database.test").Data(), ShouldEqual, "DEFINE DATABASE test")
So(res[6].Status, ShouldEqual, "OK") So(res[6].Status, ShouldEqual, "OK")
So(res[7].Status, ShouldEqual, "OK") So(res[7].Status, ShouldEqual, "OK")
So(res[8].Status, ShouldEqual, "OK") So(res[8].Status, ShouldEqual, "OK")
So(data.Consume(res[8].Result[0]).Get("login").Data(), ShouldHaveLength, 0) So(res[9].Status, ShouldEqual, "OK")
So(data.Consume(res[8].Result[0]).Get("token").Data(), ShouldHaveLength, 0) So(data.Consume(res[9].Result[0]).Get("login").Data(), ShouldHaveLength, 0)
So(data.Consume(res[8].Result[0]).Get("database").Data(), ShouldHaveLength, 0) So(data.Consume(res[9].Result[0]).Get("token").Data(), ShouldHaveLength, 0)
So(data.Consume(res[9].Result[0]).Get("database").Data(), ShouldHaveLength, 0)
}) })
@ -69,6 +71,7 @@ func TestInfo(t *testing.T) {
txt := ` txt := `
USE NS test DB test; USE NS test DB test;
DEFINE LOGIN test ON DATABASE PASSWORD "test"; DEFINE LOGIN test ON DATABASE PASSWORD "test";
DEFINE LOGIN test ON DATABASE PASSHASH "$2a$10$mofTMm4nilzRSZuU0GyuCuAgHy2mEPeNRqHZH9ETnh.O1MBjy2PDO";
DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "test"; DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "test";
DEFINE SCOPE test; DEFINE SCOPE test;
DEFINE TABLE test; DEFINE TABLE test;
@ -82,29 +85,30 @@ func TestInfo(t *testing.T) {
res, err := Execute(setupKV(), txt, nil) res, err := Execute(setupKV(), txt, nil)
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(res, ShouldHaveLength, 11) So(res, ShouldHaveLength, 12)
So(res[1].Status, ShouldEqual, "OK") So(res[1].Status, ShouldEqual, "OK")
So(res[2].Status, ShouldEqual, "OK") So(res[2].Status, ShouldEqual, "OK")
So(res[3].Status, ShouldEqual, "OK") So(res[3].Status, ShouldEqual, "OK")
So(res[4].Status, ShouldEqual, "OK") So(res[4].Status, ShouldEqual, "OK")
So(res[5].Status, ShouldEqual, "OK") So(res[5].Status, ShouldEqual, "OK")
So(data.Consume(res[5].Result[0]).Get("login").Data(), ShouldHaveLength, 1)
So(data.Consume(res[5].Result[0]).Get("login.test").Data(), ShouldEqual, "DEFINE LOGIN test ON DATABASE PASSWORD ********")
So(data.Consume(res[5].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
So(data.Consume(res[5].Result[0]).Get("token.test").Data(), ShouldEqual, "DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE ********")
So(data.Consume(res[5].Result[0]).Get("scope").Data(), ShouldHaveLength, 1)
So(data.Consume(res[5].Result[0]).Get("scope.test").Data(), ShouldEqual, "DEFINE SCOPE test")
So(data.Consume(res[5].Result[0]).Get("table").Data(), ShouldHaveLength, 1)
So(data.Consume(res[5].Result[0]).Get("table.test").Data(), ShouldEqual, "DEFINE TABLE test")
So(res[6].Status, ShouldEqual, "OK") So(res[6].Status, ShouldEqual, "OK")
So(data.Consume(res[6].Result[0]).Get("login").Data(), ShouldHaveLength, 1)
So(data.Consume(res[6].Result[0]).Get("login.test").Data(), ShouldEqual, `DEFINE LOGIN test ON DATABASE PASSHASH "$2a$10$mofTMm4nilzRSZuU0GyuCuAgHy2mEPeNRqHZH9ETnh.O1MBjy2PDO"`)
So(data.Consume(res[6].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
So(data.Consume(res[6].Result[0]).Get("token.test").Data(), ShouldEqual, `DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "test"`)
So(data.Consume(res[6].Result[0]).Get("scope").Data(), ShouldHaveLength, 1)
So(data.Consume(res[6].Result[0]).Get("scope.test").Data(), ShouldEqual, "DEFINE SCOPE test")
So(data.Consume(res[6].Result[0]).Get("table").Data(), ShouldHaveLength, 1)
So(data.Consume(res[6].Result[0]).Get("table.test").Data(), ShouldEqual, "DEFINE TABLE test")
So(res[7].Status, ShouldEqual, "OK") So(res[7].Status, ShouldEqual, "OK")
So(res[8].Status, ShouldEqual, "OK") So(res[8].Status, ShouldEqual, "OK")
So(res[9].Status, ShouldEqual, "OK") So(res[9].Status, ShouldEqual, "OK")
So(res[10].Status, ShouldEqual, "OK") So(res[10].Status, ShouldEqual, "OK")
So(data.Consume(res[10].Result[0]).Get("login").Data(), ShouldHaveLength, 0) So(res[11].Status, ShouldEqual, "OK")
So(data.Consume(res[10].Result[0]).Get("token").Data(), ShouldHaveLength, 0) So(data.Consume(res[11].Result[0]).Get("login").Data(), ShouldHaveLength, 0)
So(data.Consume(res[10].Result[0]).Get("scope").Data(), ShouldHaveLength, 0) So(data.Consume(res[11].Result[0]).Get("token").Data(), ShouldHaveLength, 0)
So(data.Consume(res[10].Result[0]).Get("table").Data(), ShouldHaveLength, 0) So(data.Consume(res[11].Result[0]).Get("scope").Data(), ShouldHaveLength, 0)
So(data.Consume(res[11].Result[0]).Get("table").Data(), ShouldHaveLength, 0)
}) })
@ -127,7 +131,7 @@ func TestInfo(t *testing.T) {
So(res[1].Status, ShouldEqual, "OK") So(res[1].Status, ShouldEqual, "OK")
So(res[2].Status, ShouldEqual, "OK") So(res[2].Status, ShouldEqual, "OK")
So(data.Consume(res[3].Result[0]).Get("token").Data(), ShouldHaveLength, 1) So(data.Consume(res[3].Result[0]).Get("token").Data(), ShouldHaveLength, 1)
So(data.Consume(res[3].Result[0]).Get("token.test").Data(), ShouldEqual, "DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE ********") So(data.Consume(res[3].Result[0]).Get("token.test").Data(), ShouldEqual, `DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE "test"`)
So(res[4].Status, ShouldEqual, "OK") So(res[4].Status, ShouldEqual, "OK")
So(res[5].Status, ShouldEqual, "OK") So(res[5].Status, ShouldEqual, "OK")
So(data.Consume(res[5].Result[0]).Get("token").Data(), ShouldHaveLength, 0) So(data.Consume(res[5].Result[0]).Get("token").Data(), ShouldHaveLength, 0)

View file

@ -305,6 +305,7 @@ type DefineLoginStatement struct {
Kind Token Kind Token
User *Ident User *Ident
Pass []byte Pass []byte
Hash []byte
Code []byte Code []byte
} }

View file

@ -42,13 +42,22 @@ func (p *parser) parseDefineLoginStatement() (stmt *DefineLoginStatement, err er
} }
} }
if _, _, err := p.shouldBe(PASSWORD); err != nil { tok, _, err := p.shouldBe(PASSWORD, PASSHASH)
if err != nil {
return nil, err return nil, err
} }
if is(tok, PASSWORD) {
if stmt.Pass, err = p.parseBinary(); err != nil { if stmt.Pass, err = p.parseBinary(); err != nil {
return nil, err return nil, err
} }
}
if is(tok, PASSHASH) {
if stmt.Hash, err = p.parseBinary(); err != nil {
return nil, err
}
}
return return

View file

@ -2180,7 +2180,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
}, },
{ {
sql: `DEFINE LOGIN test ON NAMESPACE`, sql: `DEFINE LOGIN test ON NAMESPACE`,
err: "Found `` but expected `PASSWORD`", err: "Found `` but expected `PASSWORD, PASSHASH`",
}, },
{ {
sql: `DEFINE LOGIN test ON NAMESPACE PASSWORD`, sql: `DEFINE LOGIN test ON NAMESPACE PASSWORD`,
@ -2188,7 +2188,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
}, },
{ {
sql: `DEFINE LOGIN test ON NAMESPACE PASSWORD "123456"`, sql: `DEFINE LOGIN test ON NAMESPACE PASSWORD "123456"`,
str: `DEFINE LOGIN test ON NAMESPACE PASSWORD ********`, str: `DEFINE LOGIN test ON NAMESPACE PASSHASH "123456"`,
res: &Query{Statements: []Statement{&DefineLoginStatement{ res: &Query{Statements: []Statement{&DefineLoginStatement{
KV: "*", NS: "*", DB: "*", KV: "*", NS: "*", DB: "*",
Kind: NAMESPACE, Kind: NAMESPACE,
@ -2198,7 +2198,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
}, },
{ {
sql: `DEFINE LOGIN test ON DATABASE PASSWORD "123456"`, sql: `DEFINE LOGIN test ON DATABASE PASSWORD "123456"`,
str: `DEFINE LOGIN test ON DATABASE PASSWORD ********`, str: `DEFINE LOGIN test ON DATABASE PASSHASH "123456"`,
res: &Query{Statements: []Statement{&DefineLoginStatement{ res: &Query{Statements: []Statement{&DefineLoginStatement{
KV: "*", NS: "*", DB: "*", KV: "*", NS: "*", DB: "*",
Kind: DATABASE, Kind: DATABASE,
@ -2261,7 +2261,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
}, },
{ {
sql: `DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "secret"`, sql: `DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "secret"`,
str: `DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE ********`, str: `DEFINE TOKEN test ON NAMESPACE TYPE HS512 VALUE "secret"`,
res: &Query{Statements: []Statement{&DefineTokenStatement{ res: &Query{Statements: []Statement{&DefineTokenStatement{
KV: "*", NS: "*", DB: "*", KV: "*", NS: "*", DB: "*",
Kind: NAMESPACE, Kind: NAMESPACE,
@ -2273,7 +2273,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
}, },
{ {
sql: `DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "secret"`, sql: `DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "secret"`,
str: `DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE ********`, str: `DEFINE TOKEN test ON DATABASE TYPE HS512 VALUE "secret"`,
res: &Query{Statements: []Statement{&DefineTokenStatement{ res: &Query{Statements: []Statement{&DefineTokenStatement{
KV: "*", NS: "*", DB: "*", KV: "*", NS: "*", DB: "*",
Kind: DATABASE, Kind: DATABASE,
@ -2285,7 +2285,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
}, },
{ {
sql: `DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE "secret"`, sql: `DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE "secret"`,
str: `DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE ********`, str: `DEFINE TOKEN test ON SCOPE test TYPE HS512 VALUE "secret"`,
res: &Query{Statements: []Statement{&DefineTokenStatement{ res: &Query{Statements: []Statement{&DefineTokenStatement{
KV: "*", NS: "*", DB: "*", KV: "*", NS: "*", DB: "*",
Kind: SCOPE, Kind: SCOPE,

View file

@ -92,7 +92,7 @@ func maybe(b bool, v ...interface{}) string {
} }
func binar(b []byte) string { func binar(b []byte) string {
return fmt.Sprintf(`"%s"`, b) return fmt.Sprintf("%q", b)
} }
func quote(s string) string { func quote(s string) string {
@ -321,9 +321,10 @@ func (this RemoveDatabaseStatement) String() string {
} }
func (this DefineLoginStatement) String() string { func (this DefineLoginStatement) String() string {
return print("DEFINE LOGIN %v ON %v PASSWORD ********", return print("DEFINE LOGIN %v ON %v PASSHASH %s",
this.User, this.User,
this.Kind, this.Kind,
binar(this.Pass),
) )
} }
@ -335,10 +336,11 @@ func (this RemoveLoginStatement) String() string {
} }
func (this DefineTokenStatement) String() string { func (this DefineTokenStatement) String() string {
return print("DEFINE TOKEN %v ON %v TYPE %v VALUE ********", return print("DEFINE TOKEN %v ON %v TYPE %v VALUE %s",
this.Name, this.Name,
maybe(this.Kind == SCOPE, print("%v %v", this.Kind, this.What), print("%v", this.Kind)), maybe(this.Kind == SCOPE, print("%v %v", this.Kind, this.What), print("%v", this.Kind)),
this.Type, this.Type,
binar(this.Code),
) )
} }

View file

@ -164,6 +164,7 @@ const (
OR OR
ORDER ORDER
PARALLEL PARALLEL
PASSHASH
PASSWORD PASSWORD
PERMISSIONS PERMISSIONS
PRIORITY PRIORITY
@ -339,6 +340,7 @@ var tokens = [...]string{
OR: "OR", OR: "OR",
ORDER: "ORDER", ORDER: "ORDER",
PARALLEL: "PARALLEL", PARALLEL: "PARALLEL",
PASSHASH: "PASSHASH",
PASSWORD: "PASSWORD", PASSWORD: "PASSWORD",
PERMISSIONS: "PERMISSIONS", PERMISSIONS: "PERMISSIONS",
PRIORITY: "PRIORITY", PRIORITY: "PRIORITY",