From 4e6d96b83137e00f1d22a6981222eaa092898ad4 Mon Sep 17 00:00:00 2001 From: Jason Fulghum Date: Wed, 5 Nov 2025 13:21:34 -0800 Subject: [PATCH 1/2] Add support for configuring a user's TLS connection requirements --- enginetest/queries/priv_auth_queries.go | 43 +++ sql/mysql_db/fbs/mysql_db.fbs | 4 + sql/mysql_db/mysql_db_load.go | 4 + sql/mysql_db/mysql_db_serialize.go | 8 + sql/mysql_db/serial/mysql_db.go | 475 +++++++----------------- sql/mysql_db/user.go | 42 ++- sql/rowexec/ddl.go | 28 ++ 7 files changed, 270 insertions(+), 334 deletions(-) diff --git a/enginetest/queries/priv_auth_queries.go b/enginetest/queries/priv_auth_queries.go index c074cd4592..2b8c69eaf9 100644 --- a/enginetest/queries/priv_auth_queries.go +++ b/enginetest/queries/priv_auth_queries.go @@ -22,6 +22,7 @@ import ( sqle "github.com/dolthub/go-mysql-server" "github.com/dolthub/go-mysql-server/sql" + "github.com/dolthub/go-mysql-server/sql/encodings" "github.com/dolthub/go-mysql-server/sql/mysql_db" "github.com/dolthub/go-mysql-server/sql/plan" "github.com/dolthub/go-mysql-server/sql/types" @@ -772,6 +773,48 @@ var UserPrivTests = []UserPrivilegeTest{ }, }, }, + { + Name: "User creation with SSL/TLS requirements", + SetUpScript: []string{ + "CREATE USER testuser1@`127.0.0.1` REQUIRE NONE;", + "CREATE USER testuser2@`127.0.0.1` REQUIRE SSL;", + "CREATE USER testuser3@`127.0.0.1` REQUIRE X509;", + "CREATE USER testuser4@`127.0.0.1` IDENTIFIED WITH caching_sha2_password by 'pass1' REQUIRE X509;", + "CREATE USER testuser5@`127.0.0.1` REQUIRE SUBJECT 'cert_subject';", + "CREATE USER testuser6@`127.0.0.1` REQUIRE ISSUER 'cert_issuer';", + "CREATE USER testuser7@`127.0.0.1` REQUIRE CIPHER 'cipher';", + }, + Assertions: []UserPrivilegeTestAssertion{ + { + Query: "select user, ssl_type, ssl_cipher, x509_issuer, x509_subject from mysql.user where user='testuser1';", + Expected: []sql.Row{{"testuser1", "", encodings.StringToBytes(""), encodings.StringToBytes(""), encodings.StringToBytes("")}}, + }, + { + Query: "select user, ssl_type, ssl_cipher, x509_issuer, x509_subject from mysql.user where user='testuser2';", + Expected: []sql.Row{{"testuser2", "ANY", encodings.StringToBytes(""), encodings.StringToBytes(""), encodings.StringToBytes("")}}, + }, + { + Query: "select user, ssl_type, ssl_cipher, x509_issuer, x509_subject from mysql.user where user='testuser3';", + Expected: []sql.Row{{"testuser3", "X509", encodings.StringToBytes(""), encodings.StringToBytes(""), encodings.StringToBytes("")}}, + }, + { + Query: "select user, plugin, ssl_type, ssl_cipher, x509_issuer, x509_subject from mysql.user where user='testuser4';", + Expected: []sql.Row{{"testuser4", "caching_sha2_password", "X509", encodings.StringToBytes(""), encodings.StringToBytes(""), encodings.StringToBytes("")}}, + }, + { + Query: "select user, ssl_type, ssl_cipher, x509_issuer, x509_subject from mysql.user where user='testuser5';", + Expected: []sql.Row{{"testuser5", "SPECIFIED", encodings.StringToBytes(""), encodings.StringToBytes(""), encodings.StringToBytes("cert_subject")}}, + }, + { + Query: "select user, ssl_type, ssl_cipher, x509_issuer, x509_subject from mysql.user where user='testuser6';", + Expected: []sql.Row{{"testuser6", "SPECIFIED", encodings.StringToBytes(""), encodings.StringToBytes("cert_issuer"), encodings.StringToBytes("")}}, + }, + { + Query: "select user, ssl_type, ssl_cipher, x509_issuer, x509_subject from mysql.user where user='testuser7';", + Expected: []sql.Row{{"testuser7", "SPECIFIED", encodings.StringToBytes("cipher"), encodings.StringToBytes(""), encodings.StringToBytes("")}}, + }, + }, + }, { Name: "Dynamic privilege support", SetUpScript: []string{ diff --git a/sql/mysql_db/fbs/mysql_db.fbs b/sql/mysql_db/fbs/mysql_db.fbs index f608711059..fd4ca6c7b7 100644 --- a/sql/mysql_db/fbs/mysql_db.fbs +++ b/sql/mysql_db/fbs/mysql_db.fbs @@ -54,6 +54,10 @@ table User { locked:bool; attributes:string; // represents *string identity:string; + ssl_type:string; + ssl_cipher:string; + x509_issuer:string; + x509_subject:string; } // Entries in the role_edges table diff --git a/sql/mysql_db/mysql_db_load.go b/sql/mysql_db/mysql_db_load.go index f43593fb9d..41a499fba3 100644 --- a/sql/mysql_db/mysql_db_load.go +++ b/sql/mysql_db/mysql_db_load.go @@ -137,6 +137,10 @@ func LoadUser(serialUser *serial.User) *User { Locked: serialUser.Locked(), Attributes: attributes, Identity: string(serialUser.Identity()), + SslType: string(serialUser.SslType()), + SslCipher: string(serialUser.SslCipher()), + X509Issuer: string(serialUser.X509Issuer()), + X509Subject: string(serialUser.X509Subject()), } } diff --git a/sql/mysql_db/mysql_db_serialize.go b/sql/mysql_db/mysql_db_serialize.go index 6f893aef19..1ef052e600 100644 --- a/sql/mysql_db/mysql_db_serialize.go +++ b/sql/mysql_db/mysql_db_serialize.go @@ -172,6 +172,10 @@ func serializeUser(b *flatbuffers.Builder, users []*User) flatbuffers.UOffsetT { authString := b.CreateString(user.AuthString) attributes := serializeAttributes(b, user.Attributes) identity := b.CreateString(user.Identity) + sslType := b.CreateString(user.SslType) + sslCipher := b.CreateString(user.SslCipher) + x509Issuer := b.CreateString(user.X509Issuer) + x509Subject := b.CreateString(user.X509Subject) serial.UserStart(b) serial.UserAddUser(b, userName) @@ -183,6 +187,10 @@ func serializeUser(b *flatbuffers.Builder, users []*User) flatbuffers.UOffsetT { serial.UserAddLocked(b, user.Locked) serial.UserAddAttributes(b, attributes) serial.UserAddIdentity(b, identity) + serial.UserAddSslType(b, sslType) + serial.UserAddSslCipher(b, sslCipher) + serial.UserAddX509Issuer(b, x509Issuer) + serial.UserAddX509Subject(b, x509Subject) offsets[len(users)-i-1] = serial.UserEnd(b) // reverse order } diff --git a/sql/mysql_db/serial/mysql_db.go b/sql/mysql_db/serial/mysql_db.go index e5dbfe8fc2..96f4565cf3 100644 --- a/sql/mysql_db/serial/mysql_db.go +++ b/sql/mysql_db/serial/mysql_db.go @@ -24,37 +24,28 @@ type PrivilegeSetColumn struct { _tab flatbuffers.Table } -func InitPrivilegeSetColumnRoot(o *PrivilegeSetColumn, buf []byte, offset flatbuffers.UOffsetT) error { - n := flatbuffers.GetUOffsetT(buf[offset:]) - o.Init(buf, n+offset) - if PrivilegeSetColumnNumFields < o.Table().NumFields() { - return flatbuffers.ErrTableHasUnknownFields - } - return nil -} - -func TryGetRootAsPrivilegeSetColumn(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSetColumn, error) { - x := &PrivilegeSetColumn{} - return x, InitPrivilegeSetColumnRoot(x, buf, offset) -} - func GetRootAsPrivilegeSetColumn(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSetColumn { + n := flatbuffers.GetUOffsetT(buf[offset:]) x := &PrivilegeSetColumn{} - InitPrivilegeSetColumnRoot(x, buf, offset) + x.Init(buf, n+offset) return x } -func TryGetSizePrefixedRootAsPrivilegeSetColumn(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSetColumn, error) { - x := &PrivilegeSetColumn{} - return x, InitPrivilegeSetColumnRoot(x, buf, offset+flatbuffers.SizeUint32) +func FinishPrivilegeSetColumnBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) } func GetSizePrefixedRootAsPrivilegeSetColumn(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSetColumn { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) x := &PrivilegeSetColumn{} - InitPrivilegeSetColumnRoot(x, buf, offset+flatbuffers.SizeUint32) + x.Init(buf, n+offset+flatbuffers.SizeUint32) return x } +func FinishSizePrefixedPrivilegeSetColumnBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + func (rcv *PrivilegeSetColumn) Init(buf []byte, i flatbuffers.UOffsetT) { rcv._tab.Bytes = buf rcv._tab.Pos = i @@ -98,10 +89,8 @@ func (rcv *PrivilegeSetColumn) MutatePrivs(j int, n int32) bool { return false } -const PrivilegeSetColumnNumFields = 2 - func PrivilegeSetColumnStart(builder *flatbuffers.Builder) { - builder.StartObject(PrivilegeSetColumnNumFields) + builder.StartObject(2) } func PrivilegeSetColumnAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0) @@ -120,37 +109,28 @@ type PrivilegeSetTable struct { _tab flatbuffers.Table } -func InitPrivilegeSetTableRoot(o *PrivilegeSetTable, buf []byte, offset flatbuffers.UOffsetT) error { - n := flatbuffers.GetUOffsetT(buf[offset:]) - o.Init(buf, n+offset) - if PrivilegeSetTableNumFields < o.Table().NumFields() { - return flatbuffers.ErrTableHasUnknownFields - } - return nil -} - -func TryGetRootAsPrivilegeSetTable(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSetTable, error) { - x := &PrivilegeSetTable{} - return x, InitPrivilegeSetTableRoot(x, buf, offset) -} - func GetRootAsPrivilegeSetTable(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSetTable { + n := flatbuffers.GetUOffsetT(buf[offset:]) x := &PrivilegeSetTable{} - InitPrivilegeSetTableRoot(x, buf, offset) + x.Init(buf, n+offset) return x } -func TryGetSizePrefixedRootAsPrivilegeSetTable(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSetTable, error) { - x := &PrivilegeSetTable{} - return x, InitPrivilegeSetTableRoot(x, buf, offset+flatbuffers.SizeUint32) +func FinishPrivilegeSetTableBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) } func GetSizePrefixedRootAsPrivilegeSetTable(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSetTable { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) x := &PrivilegeSetTable{} - InitPrivilegeSetTableRoot(x, buf, offset+flatbuffers.SizeUint32) + x.Init(buf, n+offset+flatbuffers.SizeUint32) return x } +func FinishSizePrefixedPrivilegeSetTableBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + func (rcv *PrivilegeSetTable) Init(buf []byte, i flatbuffers.UOffsetT) { rcv._tab.Bytes = buf rcv._tab.Pos = i @@ -206,21 +186,6 @@ func (rcv *PrivilegeSetTable) Columns(obj *PrivilegeSetColumn, j int) bool { return false } -func (rcv *PrivilegeSetTable) TryColumns(obj *PrivilegeSetColumn, j int) (bool, error) { - o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) - if o != 0 { - x := rcv._tab.Vector(o) - x += flatbuffers.UOffsetT(j) * 4 - x = rcv._tab.Indirect(x) - obj.Init(rcv._tab.Bytes, x) - if PrivilegeSetColumnNumFields < obj.Table().NumFields() { - return false, flatbuffers.ErrTableHasUnknownFields - } - return true, nil - } - return false, nil -} - func (rcv *PrivilegeSetTable) ColumnsLength() int { o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) if o != 0 { @@ -229,10 +194,8 @@ func (rcv *PrivilegeSetTable) ColumnsLength() int { return 0 } -const PrivilegeSetTableNumFields = 3 - func PrivilegeSetTableStart(builder *flatbuffers.Builder) { - builder.StartObject(PrivilegeSetTableNumFields) + builder.StartObject(3) } func PrivilegeSetTableAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0) @@ -257,37 +220,28 @@ type PrivilegeSetRoutine struct { _tab flatbuffers.Table } -func InitPrivilegeSetRoutineRoot(o *PrivilegeSetRoutine, buf []byte, offset flatbuffers.UOffsetT) error { - n := flatbuffers.GetUOffsetT(buf[offset:]) - o.Init(buf, n+offset) - if PrivilegeSetRoutineNumFields < o.Table().NumFields() { - return flatbuffers.ErrTableHasUnknownFields - } - return nil -} - -func TryGetRootAsPrivilegeSetRoutine(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSetRoutine, error) { - x := &PrivilegeSetRoutine{} - return x, InitPrivilegeSetRoutineRoot(x, buf, offset) -} - func GetRootAsPrivilegeSetRoutine(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSetRoutine { + n := flatbuffers.GetUOffsetT(buf[offset:]) x := &PrivilegeSetRoutine{} - InitPrivilegeSetRoutineRoot(x, buf, offset) + x.Init(buf, n+offset) return x } -func TryGetSizePrefixedRootAsPrivilegeSetRoutine(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSetRoutine, error) { - x := &PrivilegeSetRoutine{} - return x, InitPrivilegeSetRoutineRoot(x, buf, offset+flatbuffers.SizeUint32) +func FinishPrivilegeSetRoutineBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) } func GetSizePrefixedRootAsPrivilegeSetRoutine(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSetRoutine { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) x := &PrivilegeSetRoutine{} - InitPrivilegeSetRoutineRoot(x, buf, offset+flatbuffers.SizeUint32) + x.Init(buf, n+offset+flatbuffers.SizeUint32) return x } +func FinishSizePrefixedPrivilegeSetRoutineBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + func (rcv *PrivilegeSetRoutine) Init(buf []byte, i flatbuffers.UOffsetT) { rcv._tab.Bytes = buf rcv._tab.Pos = i @@ -343,10 +297,8 @@ func (rcv *PrivilegeSetRoutine) MutateIsProc(n bool) bool { return rcv._tab.MutateBoolSlot(8, n) } -const PrivilegeSetRoutineNumFields = 3 - func PrivilegeSetRoutineStart(builder *flatbuffers.Builder) { - builder.StartObject(PrivilegeSetRoutineNumFields) + builder.StartObject(3) } func PrivilegeSetRoutineAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0) @@ -368,37 +320,28 @@ type PrivilegeSetDatabase struct { _tab flatbuffers.Table } -func InitPrivilegeSetDatabaseRoot(o *PrivilegeSetDatabase, buf []byte, offset flatbuffers.UOffsetT) error { - n := flatbuffers.GetUOffsetT(buf[offset:]) - o.Init(buf, n+offset) - if PrivilegeSetDatabaseNumFields < o.Table().NumFields() { - return flatbuffers.ErrTableHasUnknownFields - } - return nil -} - -func TryGetRootAsPrivilegeSetDatabase(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSetDatabase, error) { - x := &PrivilegeSetDatabase{} - return x, InitPrivilegeSetDatabaseRoot(x, buf, offset) -} - func GetRootAsPrivilegeSetDatabase(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSetDatabase { + n := flatbuffers.GetUOffsetT(buf[offset:]) x := &PrivilegeSetDatabase{} - InitPrivilegeSetDatabaseRoot(x, buf, offset) + x.Init(buf, n+offset) return x } -func TryGetSizePrefixedRootAsPrivilegeSetDatabase(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSetDatabase, error) { - x := &PrivilegeSetDatabase{} - return x, InitPrivilegeSetDatabaseRoot(x, buf, offset+flatbuffers.SizeUint32) +func FinishPrivilegeSetDatabaseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) } func GetSizePrefixedRootAsPrivilegeSetDatabase(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSetDatabase { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) x := &PrivilegeSetDatabase{} - InitPrivilegeSetDatabaseRoot(x, buf, offset+flatbuffers.SizeUint32) + x.Init(buf, n+offset+flatbuffers.SizeUint32) return x } +func FinishSizePrefixedPrivilegeSetDatabaseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + func (rcv *PrivilegeSetDatabase) Init(buf []byte, i flatbuffers.UOffsetT) { rcv._tab.Bytes = buf rcv._tab.Pos = i @@ -454,21 +397,6 @@ func (rcv *PrivilegeSetDatabase) Tables(obj *PrivilegeSetTable, j int) bool { return false } -func (rcv *PrivilegeSetDatabase) TryTables(obj *PrivilegeSetTable, j int) (bool, error) { - o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) - if o != 0 { - x := rcv._tab.Vector(o) - x += flatbuffers.UOffsetT(j) * 4 - x = rcv._tab.Indirect(x) - obj.Init(rcv._tab.Bytes, x) - if PrivilegeSetTableNumFields < obj.Table().NumFields() { - return false, flatbuffers.ErrTableHasUnknownFields - } - return true, nil - } - return false, nil -} - func (rcv *PrivilegeSetDatabase) TablesLength() int { o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) if o != 0 { @@ -489,21 +417,6 @@ func (rcv *PrivilegeSetDatabase) Routines(obj *PrivilegeSetRoutine, j int) bool return false } -func (rcv *PrivilegeSetDatabase) TryRoutines(obj *PrivilegeSetRoutine, j int) (bool, error) { - o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) - if o != 0 { - x := rcv._tab.Vector(o) - x += flatbuffers.UOffsetT(j) * 4 - x = rcv._tab.Indirect(x) - obj.Init(rcv._tab.Bytes, x) - if PrivilegeSetRoutineNumFields < obj.Table().NumFields() { - return false, flatbuffers.ErrTableHasUnknownFields - } - return true, nil - } - return false, nil -} - func (rcv *PrivilegeSetDatabase) RoutinesLength() int { o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) if o != 0 { @@ -512,10 +425,8 @@ func (rcv *PrivilegeSetDatabase) RoutinesLength() int { return 0 } -const PrivilegeSetDatabaseNumFields = 4 - func PrivilegeSetDatabaseStart(builder *flatbuffers.Builder) { - builder.StartObject(PrivilegeSetDatabaseNumFields) + builder.StartObject(4) } func PrivilegeSetDatabaseAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0) @@ -546,37 +457,28 @@ type PrivilegeSet struct { _tab flatbuffers.Table } -func InitPrivilegeSetRoot(o *PrivilegeSet, buf []byte, offset flatbuffers.UOffsetT) error { - n := flatbuffers.GetUOffsetT(buf[offset:]) - o.Init(buf, n+offset) - if PrivilegeSetNumFields < o.Table().NumFields() { - return flatbuffers.ErrTableHasUnknownFields - } - return nil -} - -func TryGetRootAsPrivilegeSet(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSet, error) { - x := &PrivilegeSet{} - return x, InitPrivilegeSetRoot(x, buf, offset) -} - func GetRootAsPrivilegeSet(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSet { + n := flatbuffers.GetUOffsetT(buf[offset:]) x := &PrivilegeSet{} - InitPrivilegeSetRoot(x, buf, offset) + x.Init(buf, n+offset) return x } -func TryGetSizePrefixedRootAsPrivilegeSet(buf []byte, offset flatbuffers.UOffsetT) (*PrivilegeSet, error) { - x := &PrivilegeSet{} - return x, InitPrivilegeSetRoot(x, buf, offset+flatbuffers.SizeUint32) +func FinishPrivilegeSetBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) } func GetSizePrefixedRootAsPrivilegeSet(buf []byte, offset flatbuffers.UOffsetT) *PrivilegeSet { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) x := &PrivilegeSet{} - InitPrivilegeSetRoot(x, buf, offset+flatbuffers.SizeUint32) + x.Init(buf, n+offset+flatbuffers.SizeUint32) return x } +func FinishSizePrefixedPrivilegeSetBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + func (rcv *PrivilegeSet) Init(buf []byte, i flatbuffers.UOffsetT) { rcv._tab.Bytes = buf rcv._tab.Pos = i @@ -641,21 +543,6 @@ func (rcv *PrivilegeSet) Databases(obj *PrivilegeSetDatabase, j int) bool { return false } -func (rcv *PrivilegeSet) TryDatabases(obj *PrivilegeSetDatabase, j int) (bool, error) { - o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) - if o != 0 { - x := rcv._tab.Vector(o) - x += flatbuffers.UOffsetT(j) * 4 - x = rcv._tab.Indirect(x) - obj.Init(rcv._tab.Bytes, x) - if PrivilegeSetDatabaseNumFields < obj.Table().NumFields() { - return false, flatbuffers.ErrTableHasUnknownFields - } - return true, nil - } - return false, nil -} - func (rcv *PrivilegeSet) DatabasesLength() int { o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) if o != 0 { @@ -690,10 +577,8 @@ func (rcv *PrivilegeSet) MutateGlobalDynamicWgo(j int, n bool) bool { return false } -const PrivilegeSetNumFields = 4 - func PrivilegeSetStart(builder *flatbuffers.Builder) { - builder.StartObject(PrivilegeSetNumFields) + builder.StartObject(4) } func PrivilegeSetAddGlobalStatic(builder *flatbuffers.Builder, globalStatic flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(globalStatic), 0) @@ -727,37 +612,28 @@ type User struct { _tab flatbuffers.Table } -func InitUserRoot(o *User, buf []byte, offset flatbuffers.UOffsetT) error { - n := flatbuffers.GetUOffsetT(buf[offset:]) - o.Init(buf, n+offset) - if UserNumFields < o.Table().NumFields() { - return flatbuffers.ErrTableHasUnknownFields - } - return nil -} - -func TryGetRootAsUser(buf []byte, offset flatbuffers.UOffsetT) (*User, error) { - x := &User{} - return x, InitUserRoot(x, buf, offset) -} - func GetRootAsUser(buf []byte, offset flatbuffers.UOffsetT) *User { + n := flatbuffers.GetUOffsetT(buf[offset:]) x := &User{} - InitUserRoot(x, buf, offset) + x.Init(buf, n+offset) return x } -func TryGetSizePrefixedRootAsUser(buf []byte, offset flatbuffers.UOffsetT) (*User, error) { - x := &User{} - return x, InitUserRoot(x, buf, offset+flatbuffers.SizeUint32) +func FinishUserBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) } func GetSizePrefixedRootAsUser(buf []byte, offset flatbuffers.UOffsetT) *User { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) x := &User{} - InitUserRoot(x, buf, offset+flatbuffers.SizeUint32) + x.Init(buf, n+offset+flatbuffers.SizeUint32) return x } +func FinishSizePrefixedUserBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + func (rcv *User) Init(buf []byte, i flatbuffers.UOffsetT) { rcv._tab.Bytes = buf rcv._tab.Pos = i @@ -796,22 +672,6 @@ func (rcv *User) PrivilegeSet(obj *PrivilegeSet) *PrivilegeSet { return nil } -func (rcv *User) TryPrivilegeSet(obj *PrivilegeSet) (*PrivilegeSet, error) { - o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) - if o != 0 { - x := rcv._tab.Indirect(o + rcv._tab.Pos) - if obj == nil { - obj = new(PrivilegeSet) - } - obj.Init(rcv._tab.Bytes, x) - if PrivilegeSetNumFields < obj.Table().NumFields() { - return nil, flatbuffers.ErrTableHasUnknownFields - } - return obj, nil - } - return nil, nil -} - func (rcv *User) Plugin() []byte { o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) if o != 0 { @@ -868,10 +728,40 @@ func (rcv *User) Identity() []byte { return nil } -const UserNumFields = 9 +func (rcv *User) SslType() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(22)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + +func (rcv *User) SslCipher() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(24)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + +func (rcv *User) X509Issuer() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(26)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + +func (rcv *User) X509Subject() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(28)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} func UserStart(builder *flatbuffers.Builder) { - builder.StartObject(UserNumFields) + builder.StartObject(13) } func UserAddUser(builder *flatbuffers.Builder, user flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(user), 0) @@ -900,6 +790,18 @@ func UserAddAttributes(builder *flatbuffers.Builder, attributes flatbuffers.UOff func UserAddIdentity(builder *flatbuffers.Builder, identity flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(8, flatbuffers.UOffsetT(identity), 0) } +func UserAddSslType(builder *flatbuffers.Builder, sslType flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(9, flatbuffers.UOffsetT(sslType), 0) +} +func UserAddSslCipher(builder *flatbuffers.Builder, sslCipher flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(10, flatbuffers.UOffsetT(sslCipher), 0) +} +func UserAddX509Issuer(builder *flatbuffers.Builder, x509Issuer flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(11, flatbuffers.UOffsetT(x509Issuer), 0) +} +func UserAddX509Subject(builder *flatbuffers.Builder, x509Subject flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(12, flatbuffers.UOffsetT(x509Subject), 0) +} func UserEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } @@ -908,37 +810,28 @@ type RoleEdge struct { _tab flatbuffers.Table } -func InitRoleEdgeRoot(o *RoleEdge, buf []byte, offset flatbuffers.UOffsetT) error { - n := flatbuffers.GetUOffsetT(buf[offset:]) - o.Init(buf, n+offset) - if RoleEdgeNumFields < o.Table().NumFields() { - return flatbuffers.ErrTableHasUnknownFields - } - return nil -} - -func TryGetRootAsRoleEdge(buf []byte, offset flatbuffers.UOffsetT) (*RoleEdge, error) { - x := &RoleEdge{} - return x, InitRoleEdgeRoot(x, buf, offset) -} - func GetRootAsRoleEdge(buf []byte, offset flatbuffers.UOffsetT) *RoleEdge { + n := flatbuffers.GetUOffsetT(buf[offset:]) x := &RoleEdge{} - InitRoleEdgeRoot(x, buf, offset) + x.Init(buf, n+offset) return x } -func TryGetSizePrefixedRootAsRoleEdge(buf []byte, offset flatbuffers.UOffsetT) (*RoleEdge, error) { - x := &RoleEdge{} - return x, InitRoleEdgeRoot(x, buf, offset+flatbuffers.SizeUint32) +func FinishRoleEdgeBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) } func GetSizePrefixedRootAsRoleEdge(buf []byte, offset flatbuffers.UOffsetT) *RoleEdge { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) x := &RoleEdge{} - InitRoleEdgeRoot(x, buf, offset+flatbuffers.SizeUint32) + x.Init(buf, n+offset+flatbuffers.SizeUint32) return x } +func FinishSizePrefixedRoleEdgeBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + func (rcv *RoleEdge) Init(buf []byte, i flatbuffers.UOffsetT) { rcv._tab.Bytes = buf rcv._tab.Pos = i @@ -992,10 +885,8 @@ func (rcv *RoleEdge) MutateWithAdminOption(n bool) bool { return rcv._tab.MutateBoolSlot(12, n) } -const RoleEdgeNumFields = 5 - func RoleEdgeStart(builder *flatbuffers.Builder) { - builder.StartObject(RoleEdgeNumFields) + builder.StartObject(5) } func RoleEdgeAddFromHost(builder *flatbuffers.Builder, fromHost flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(fromHost), 0) @@ -1020,37 +911,28 @@ type ReplicaSourceInfo struct { _tab flatbuffers.Table } -func InitReplicaSourceInfoRoot(o *ReplicaSourceInfo, buf []byte, offset flatbuffers.UOffsetT) error { - n := flatbuffers.GetUOffsetT(buf[offset:]) - o.Init(buf, n+offset) - if ReplicaSourceInfoNumFields < o.Table().NumFields() { - return flatbuffers.ErrTableHasUnknownFields - } - return nil -} - -func TryGetRootAsReplicaSourceInfo(buf []byte, offset flatbuffers.UOffsetT) (*ReplicaSourceInfo, error) { - x := &ReplicaSourceInfo{} - return x, InitReplicaSourceInfoRoot(x, buf, offset) -} - func GetRootAsReplicaSourceInfo(buf []byte, offset flatbuffers.UOffsetT) *ReplicaSourceInfo { + n := flatbuffers.GetUOffsetT(buf[offset:]) x := &ReplicaSourceInfo{} - InitReplicaSourceInfoRoot(x, buf, offset) + x.Init(buf, n+offset) return x } -func TryGetSizePrefixedRootAsReplicaSourceInfo(buf []byte, offset flatbuffers.UOffsetT) (*ReplicaSourceInfo, error) { - x := &ReplicaSourceInfo{} - return x, InitReplicaSourceInfoRoot(x, buf, offset+flatbuffers.SizeUint32) +func FinishReplicaSourceInfoBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) } func GetSizePrefixedRootAsReplicaSourceInfo(buf []byte, offset flatbuffers.UOffsetT) *ReplicaSourceInfo { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) x := &ReplicaSourceInfo{} - InitReplicaSourceInfoRoot(x, buf, offset+flatbuffers.SizeUint32) + x.Init(buf, n+offset+flatbuffers.SizeUint32) return x } +func FinishSizePrefixedReplicaSourceInfoBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + func (rcv *ReplicaSourceInfo) Init(buf []byte, i flatbuffers.UOffsetT) { rcv._tab.Bytes = buf rcv._tab.Pos = i @@ -1128,10 +1010,8 @@ func (rcv *ReplicaSourceInfo) MutateConnectRetryCount(n uint64) bool { return rcv._tab.MutateUint64Slot(16, n) } -const ReplicaSourceInfoNumFields = 7 - func ReplicaSourceInfoStart(builder *flatbuffers.Builder) { - builder.StartObject(ReplicaSourceInfoNumFields) + builder.StartObject(7) } func ReplicaSourceInfoAddHost(builder *flatbuffers.Builder, host flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(host), 0) @@ -1162,37 +1042,28 @@ type MySQLDb struct { _tab flatbuffers.Table } -func InitMySQLDbRoot(o *MySQLDb, buf []byte, offset flatbuffers.UOffsetT) error { - n := flatbuffers.GetUOffsetT(buf[offset:]) - o.Init(buf, n+offset) - if MySQLDbNumFields < o.Table().NumFields() { - return flatbuffers.ErrTableHasUnknownFields - } - return nil -} - -func TryGetRootAsMySQLDb(buf []byte, offset flatbuffers.UOffsetT) (*MySQLDb, error) { - x := &MySQLDb{} - return x, InitMySQLDbRoot(x, buf, offset) -} - func GetRootAsMySQLDb(buf []byte, offset flatbuffers.UOffsetT) *MySQLDb { + n := flatbuffers.GetUOffsetT(buf[offset:]) x := &MySQLDb{} - InitMySQLDbRoot(x, buf, offset) + x.Init(buf, n+offset) return x } -func TryGetSizePrefixedRootAsMySQLDb(buf []byte, offset flatbuffers.UOffsetT) (*MySQLDb, error) { - x := &MySQLDb{} - return x, InitMySQLDbRoot(x, buf, offset+flatbuffers.SizeUint32) +func FinishMySQLDbBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.Finish(offset) } func GetSizePrefixedRootAsMySQLDb(buf []byte, offset flatbuffers.UOffsetT) *MySQLDb { + n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:]) x := &MySQLDb{} - InitMySQLDbRoot(x, buf, offset+flatbuffers.SizeUint32) + x.Init(buf, n+offset+flatbuffers.SizeUint32) return x } +func FinishSizePrefixedMySQLDbBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) { + builder.FinishSizePrefixed(offset) +} + func (rcv *MySQLDb) Init(buf []byte, i flatbuffers.UOffsetT) { rcv._tab.Bytes = buf rcv._tab.Pos = i @@ -1214,21 +1085,6 @@ func (rcv *MySQLDb) User(obj *User, j int) bool { return false } -func (rcv *MySQLDb) TryUser(obj *User, j int) (bool, error) { - o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) - if o != 0 { - x := rcv._tab.Vector(o) - x += flatbuffers.UOffsetT(j) * 4 - x = rcv._tab.Indirect(x) - obj.Init(rcv._tab.Bytes, x) - if UserNumFields < obj.Table().NumFields() { - return false, flatbuffers.ErrTableHasUnknownFields - } - return true, nil - } - return false, nil -} - func (rcv *MySQLDb) UserLength() int { o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) if o != 0 { @@ -1249,21 +1105,6 @@ func (rcv *MySQLDb) RoleEdges(obj *RoleEdge, j int) bool { return false } -func (rcv *MySQLDb) TryRoleEdges(obj *RoleEdge, j int) (bool, error) { - o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) - if o != 0 { - x := rcv._tab.Vector(o) - x += flatbuffers.UOffsetT(j) * 4 - x = rcv._tab.Indirect(x) - obj.Init(rcv._tab.Bytes, x) - if RoleEdgeNumFields < obj.Table().NumFields() { - return false, flatbuffers.ErrTableHasUnknownFields - } - return true, nil - } - return false, nil -} - func (rcv *MySQLDb) RoleEdgesLength() int { o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) if o != 0 { @@ -1284,21 +1125,6 @@ func (rcv *MySQLDb) ReplicaSourceInfo(obj *ReplicaSourceInfo, j int) bool { return false } -func (rcv *MySQLDb) TryReplicaSourceInfo(obj *ReplicaSourceInfo, j int) (bool, error) { - o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) - if o != 0 { - x := rcv._tab.Vector(o) - x += flatbuffers.UOffsetT(j) * 4 - x = rcv._tab.Indirect(x) - obj.Init(rcv._tab.Bytes, x) - if ReplicaSourceInfoNumFields < obj.Table().NumFields() { - return false, flatbuffers.ErrTableHasUnknownFields - } - return true, nil - } - return false, nil -} - func (rcv *MySQLDb) ReplicaSourceInfoLength() int { o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) if o != 0 { @@ -1319,21 +1145,6 @@ func (rcv *MySQLDb) SuperUser(obj *User, j int) bool { return false } -func (rcv *MySQLDb) TrySuperUser(obj *User, j int) (bool, error) { - o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) - if o != 0 { - x := rcv._tab.Vector(o) - x += flatbuffers.UOffsetT(j) * 4 - x = rcv._tab.Indirect(x) - obj.Init(rcv._tab.Bytes, x) - if UserNumFields < obj.Table().NumFields() { - return false, flatbuffers.ErrTableHasUnknownFields - } - return true, nil - } - return false, nil -} - func (rcv *MySQLDb) SuperUserLength() int { o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) if o != 0 { @@ -1342,10 +1153,8 @@ func (rcv *MySQLDb) SuperUserLength() int { return 0 } -const MySQLDbNumFields = 4 - func MySQLDbStart(builder *flatbuffers.Builder) { - builder.StartObject(MySQLDbNumFields) + builder.StartObject(4) } func MySQLDbAddUser(builder *flatbuffers.Builder, user flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(user), 0) diff --git a/sql/mysql_db/user.go b/sql/mysql_db/user.go index be96466aff..b99578085c 100644 --- a/sql/mysql_db/user.go +++ b/sql/mysql_db/user.go @@ -42,6 +42,11 @@ type User struct { // for the lifetime of the server process and will not be persisted to disk. IsEphemeral bool + SslType string + SslCipher string + X509Subject string + X509Issuer string + // IsRole is an additional field that states whether the User represents a role or user. In MySQL this must be a // hidden column, therefore it's represented here as an additional field. IsRole bool @@ -70,6 +75,11 @@ func UserToRow(ctx *sql.Context, u *User) (sql.Row, error) { if u.Attributes != nil { row[userTblColIndex_User_attributes] = *u.Attributes } + row[userTblColIndex_ssl_type] = u.SslType + row[userTblColIndex_ssl_cipher] = []uint8(u.SslCipher) + row[userTblColIndex_x509_issuer] = []uint8(u.X509Issuer) + row[userTblColIndex_x509_subject] = []uint8(u.X509Subject) + u.privSetToRow(ctx, row) return row, nil } @@ -87,6 +97,28 @@ func UserFromRow(ctx *sql.Context, row sql.Row) (*User, error) { if val, ok := row[userTblColIndex_password_last_changed].(time.Time); ok { passwordLastChanged = val } + + // NOTE: Depending on whether we connect via a SQL connection or directly through the Go code, + // we seem to get a different type representation for the ssl_type enum value. + var sslType string + switch row[userTblColIndex_ssl_type].(type) { + case string: + sslType = row[userTblColIndex_ssl_type].(string) + case uint16: + sslTypeType := userTblSchema[userTblColIndex_ssl_type].Type + sslTypeEnum, ok := sslTypeType.(sql.EnumType) + if !ok { + return nil, fmt.Errorf("unable to load enum type for ssl_type: %T", sslTypeType) + } + sslType, ok = sslTypeEnum.At(int(row[userTblColIndex_ssl_type].(uint16))) + if !ok { + return nil, fmt.Errorf("unable to load enum value for ssl_type with id %v", + row[userTblColIndex_ssl_type].(uint16)) + } + default: + return nil, fmt.Errorf("unexpected type for ssl_type value: %T", row[userTblColIndex_ssl_type]) + } + return &User{ User: row[userTblColIndex_User].(string), Host: row[userTblColIndex_Host].(string), @@ -98,6 +130,10 @@ func UserFromRow(ctx *sql.Context, row sql.Row) (*User, error) { Attributes: attributes, Identity: row[userTblColIndex_identity].(string), IsRole: false, + SslType: sslType, + SslCipher: string(row[userTblColIndex_ssl_cipher].([]uint8)), + X509Issuer: string(row[userTblColIndex_x509_issuer].([]uint8)), + X509Subject: string(row[userTblColIndex_x509_subject].([]uint8)), }, nil } @@ -129,7 +165,11 @@ func UserEquals(left, right *User) bool { !left.PrivilegeSet.Equals(right.PrivilegeSet) || left.Attributes == nil && right.Attributes != nil || left.Attributes != nil && right.Attributes == nil || - (left.Attributes != nil && *left.Attributes != *right.Attributes) { + (left.Attributes != nil && *left.Attributes != *right.Attributes) || + left.SslType != right.SslType || + left.X509Issuer != right.X509Issuer || + left.X509Subject != right.X509Subject || + left.SslCipher != right.SslCipher { return false } return true diff --git a/sql/rowexec/ddl.go b/sql/rowexec/ddl.go index 668490d70a..483defa5e4 100644 --- a/sql/rowexec/ddl.go +++ b/sql/rowexec/ddl.go @@ -629,6 +629,7 @@ func (b *BaseBuilder) buildCreateUser(ctx *sql.Context, n *plan.CreateUser, _ sq // TODO: attributes should probably not be nil, but setting it to &n.Attribute causes unexpected behavior // TODO: validate all of the data + sslType, sslCipher, x509Issuer, x509Subject := parseTlsOptions(n.TLSOptions) editor.PutUser(&mysql_db.User{ User: user.UserName.Name, Host: user.UserName.Host, @@ -640,6 +641,10 @@ func (b *BaseBuilder) buildCreateUser(ctx *sql.Context, n *plan.CreateUser, _ sq Attributes: nil, IsRole: false, Identity: user.Identity, + SslType: sslType, + X509Issuer: x509Issuer, + X509Subject: x509Subject, + SslCipher: sslCipher, }) } if err := mysqlDb.Persist(ctx, editor); err != nil { @@ -648,6 +653,29 @@ func (b *BaseBuilder) buildCreateUser(ctx *sql.Context, n *plan.CreateUser, _ sq return rowIterWithOkResultWithZeroRowsAffected(), nil } +// parseTlsOptions examples |tlsOptions| and returns the sslType, sslCipher, x509Issuer, and x509Subject values. If |tlsOptions| is nil, +// then all returned values are empty strings. All returned values are the values MySQL shows in the mysql.user system table, for the +// columns with the same names. +func parseTlsOptions(tlsOptions *plan.TLSOptions) (sslType string, sslCipher string, x509Issuer string, x509Subject string) { + if tlsOptions == nil { + return + } + + if tlsOptions.X509 { + sslType = "X509" + } else if tlsOptions.SSL { + sslType = "ANY" + } + if tlsOptions.Cipher != "" || tlsOptions.Subject != "" || tlsOptions.Issuer != "" { + sslType = "SPECIFIED" + } + + x509Issuer = tlsOptions.Issuer + x509Subject = tlsOptions.Subject + sslCipher = tlsOptions.Cipher + return +} + func (b *BaseBuilder) buildAlterPK(ctx *sql.Context, n *plan.AlterPK, row sql.Row) (sql.RowIter, error) { // We need to get the current table from the database because this statement could be one clause in an alter table // statement and the table may have changed since the analysis phase From 4177216b1f1d608f3e2627f428f95bae07d0a071 Mon Sep 17 00:00:00 2001 From: Jason Fulghum Date: Mon, 10 Nov 2025 10:12:25 -0800 Subject: [PATCH 2/2] PR Feedback: Calling out the BLOB storage representation for ssl_cipher, x509_issuer, and x509_subject --- sql/mysql_db/user.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sql/mysql_db/user.go b/sql/mysql_db/user.go index b99578085c..b9e8126f52 100644 --- a/sql/mysql_db/user.go +++ b/sql/mysql_db/user.go @@ -76,9 +76,11 @@ func UserToRow(ctx *sql.Context, u *User) (sql.Row, error) { row[userTblColIndex_User_attributes] = *u.Attributes } row[userTblColIndex_ssl_type] = u.SslType - row[userTblColIndex_ssl_cipher] = []uint8(u.SslCipher) - row[userTblColIndex_x509_issuer] = []uint8(u.X509Issuer) - row[userTblColIndex_x509_subject] = []uint8(u.X509Subject) + // ssl_cipher, x509_issuer, x509_subject are all represented as BLOBs, + // so we must return a byte slice instead of a string. + row[userTblColIndex_ssl_cipher] = []byte(u.SslCipher) + row[userTblColIndex_x509_issuer] = []byte(u.X509Issuer) + row[userTblColIndex_x509_subject] = []byte(u.X509Subject) u.privSetToRow(ctx, row) return row, nil @@ -131,9 +133,9 @@ func UserFromRow(ctx *sql.Context, row sql.Row) (*User, error) { Identity: row[userTblColIndex_identity].(string), IsRole: false, SslType: sslType, - SslCipher: string(row[userTblColIndex_ssl_cipher].([]uint8)), - X509Issuer: string(row[userTblColIndex_x509_issuer].([]uint8)), - X509Subject: string(row[userTblColIndex_x509_subject].([]uint8)), + SslCipher: string(row[userTblColIndex_ssl_cipher].([]byte)), + X509Issuer: string(row[userTblColIndex_x509_issuer].([]byte)), + X509Subject: string(row[userTblColIndex_x509_subject].([]byte)), }, nil }