Support exporting SQL LOGIN and SQL TOKEN hashes
This commit is contained in:
parent
26b138b9b0
commit
20abadf41f
7 changed files with 60 additions and 37 deletions
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
sql/login.go
11
sql/login.go
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in a new issue