[analyze] Add Analyzer for MySQL (#3193)

* implement analyzer interface for mysql

* add integration test for mysql analyzer

* linked detectors with analyzers for jdbc and mysql
validation for connection string in analyzer

* refactored secretInfoToAnalyzerResult func

* generated permissions for mysql analyzer

* [chore]
- optimization in execution flow
- use test-container library for analyze test.

* added host in secret info struct
simplified the mysql test due to huge structure

---------

Co-authored-by: Abdul Basit <abasit@folio3.com>
This commit is contained in:
Abdul Basit 2024-09-12 23:48:34 +05:00 committed by GitHub
parent e89190f3ed
commit b0318a9edb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 835 additions and 2 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,3 +1,5 @@
//go:generate generate_permissions permissions.yaml permissions.go mysql
package mysql
import (
@ -17,8 +19,189 @@ import (
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/config"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/pb/analyzerpb"
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
)
var _ analyzers.Analyzer = (*Analyzer)(nil)
type Analyzer struct {
Cfg *config.Config
}
func (Analyzer) Type() analyzerpb.AnalyzerType { return analyzerpb.AnalyzerType_MySQL }
func (a Analyzer) Analyze(_ context.Context, credInfo map[string]string) (*analyzers.AnalyzerResult, error) {
uri, ok := credInfo["connection_string"]
if !ok {
return nil, fmt.Errorf("missing connection string")
}
info, err := AnalyzePermissions(a.Cfg, uri)
if err != nil {
return nil, err
}
return secretInfoToAnalyzerResult(info), nil
}
func secretInfoToAnalyzerResult(info *SecretInfo) *analyzers.AnalyzerResult {
if info == nil {
return nil
}
result := analyzers.AnalyzerResult{
AnalyzerType: analyzerpb.AnalyzerType_MySQL,
Metadata: nil,
Bindings: []analyzers.Binding{},
}
// add user priviliges to bindings
userBindings, userResource := bakeUserBindings(info)
result.Bindings = append(result.Bindings, userBindings...)
// add user's database priviliges to bindings
databaseBindings := bakeDatabaseBindings(userResource, info)
result.Bindings = append(result.Bindings, databaseBindings...)
return &result
}
func bakeUserBindings(info *SecretInfo) ([]analyzers.Binding, *analyzers.Resource) {
var userBindings []analyzers.Binding
// add user and their priviliges to bindings
userResource := analyzers.Resource{
Name: info.User,
FullyQualifiedName: info.Host + "/" + info.User,
Type: "user",
}
for _, priv := range info.GlobalPrivs.Privs {
userBindings = append(userBindings, analyzers.Binding{
Resource: userResource,
Permission: analyzers.Permission{
Value: priv,
},
})
}
return userBindings, &userResource
}
func bakeDatabaseBindings(userResource *analyzers.Resource, info *SecretInfo) []analyzers.Binding {
var databaseBindings []analyzers.Binding
for _, database := range info.Databases {
dbResource := analyzers.Resource{
Name: database.Name,
FullyQualifiedName: info.Host + "/" + database.Name,
Type: "database",
Metadata: map[string]any{
"default": database.Default,
"non_existent": database.Nonexistent,
},
Parent: userResource,
}
for _, priv := range database.Privs {
databaseBindings = append(databaseBindings, analyzers.Binding{
Resource: dbResource,
Permission: analyzers.Permission{
Value: priv,
},
})
}
// add this database's table privileges to bindings
tableBindings := bakeTableBindings(&dbResource, database)
databaseBindings = append(databaseBindings, tableBindings...)
// add this database's routines privileges to bindings
routineBindings := bakeRoutineBindings(&dbResource, database)
databaseBindings = append(databaseBindings, routineBindings...)
}
return databaseBindings
}
func bakeTableBindings(dbResource *analyzers.Resource, database *Database) []analyzers.Binding {
if database.Tables == nil {
return nil
}
var tableBindings []analyzers.Binding
for _, table := range *database.Tables {
tableResource := analyzers.Resource{
Name: table.Name,
FullyQualifiedName: dbResource.FullyQualifiedName + "/" + table.Name,
Type: "table",
Metadata: map[string]any{
"bytes": table.Bytes,
"non_existent": table.Nonexistent,
},
Parent: dbResource,
}
for _, priv := range table.Privs {
tableBindings = append(tableBindings, analyzers.Binding{
Resource: tableResource,
Permission: analyzers.Permission{
Value: priv,
},
})
}
// Add this table's column privileges to bindings
for _, column := range table.Columns {
columnResource := analyzers.Resource{
Name: column.Name,
FullyQualifiedName: tableResource.FullyQualifiedName + "/" + column.Name,
Type: "column",
Parent: &tableResource,
}
for _, priv := range column.Privs {
tableBindings = append(tableBindings, analyzers.Binding{
Resource: columnResource,
Permission: analyzers.Permission{
Value: priv,
},
})
}
}
}
return tableBindings
}
func bakeRoutineBindings(dbResource *analyzers.Resource, database *Database) []analyzers.Binding {
if database.Routines == nil {
return nil
}
var routineBindings []analyzers.Binding
for _, routine := range *database.Routines {
routineResource := analyzers.Resource{
Name: routine.Name,
FullyQualifiedName: dbResource.FullyQualifiedName + "/" + routine.Name,
Type: "routine",
Metadata: map[string]any{
"non_existent": routine.Nonexistent,
},
Parent: dbResource,
}
for _, priv := range routine.Privs {
routineBindings = append(routineBindings, analyzers.Binding{
Resource: routineResource,
Permission: analyzers.Permission{
Value: priv,
},
})
}
}
return routineBindings
}
const (
// MySQL SSL Modes
mysql_sslmode = "ssl-mode"
@ -74,6 +257,7 @@ type Routine struct {
// USER() returns `doadmin@localhost`
type SecretInfo struct {
Host string
User string
Databases map[string]*Database
GlobalPrivs GlobalPrivs
@ -99,8 +283,13 @@ func AnalyzeAndPrintPermissions(cfg *config.Config, key string) {
}
func AnalyzePermissions(cfg *config.Config, connectionStr string) (*SecretInfo, error) {
// Parse the connection string
u, err := parseConnectionStr(connectionStr)
if err != nil {
return nil, fmt.Errorf("parsing the connection string: %w", err)
}
db, err := createConnection(connectionStr)
db, err := createConnection(u)
if err != nil {
return nil, fmt.Errorf("connecting to the MySQL database: %w", err)
}
@ -139,13 +328,14 @@ func AnalyzePermissions(cfg *config.Config, connectionStr string) (*SecretInfo,
processGrants(grants, databases, &globalPrivs)
return &SecretInfo{
Host: u.Hostname(),
User: user,
Databases: databases,
GlobalPrivs: globalPrivs,
}, nil
}
func createConnection(connection string) (*sql.DB, error) {
func parseConnectionStr(connection string) (*dburl.URL, error) {
// Check if the connection string starts with 'mysql://'
if !strings.HasPrefix(connection, "mysql://") {
color.Yellow("[i] The connection string should start with 'mysql://'. Adding it for you.")
@ -163,7 +353,10 @@ func createConnection(connection string) (*sql.DB, error) {
if err != nil {
return nil, err
}
return u, nil
}
func createConnection(u *dburl.URL) (*sql.DB, error) {
// Connect to the MySQL database
db, err := sql.Open("mysql", u.DSN)
if err != nil {

View file

@ -0,0 +1,104 @@
package mysql
import (
_ "embed"
"encoding/json"
"fmt"
"testing"
"github.com/brianvoe/gofakeit/v7"
"github.com/google/go-cmp/cmp"
"github.com/testcontainers/testcontainers-go/modules/mysql"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/config"
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
)
//go:embed expected_output.json
var expectedOutput []byte
func TestAnalyzer_Analyze(t *testing.T) {
mysqlUser := "root"
mysqlPass := gofakeit.Password(true, true, true, false, false, 10)
mysqlDatabase := "mysql"
ctx := context.Background()
mysqlC, err := mysql.Run(ctx, "mysql",
mysql.WithDatabase(mysqlDatabase),
mysql.WithUsername(mysqlUser),
mysql.WithPassword(mysqlPass),
)
if err != nil {
t.Fatal(err)
}
defer func() { _ = mysqlC.Terminate(ctx) }()
host, err := mysqlC.Host(ctx)
if err != nil {
t.Fatal(err)
}
port, err := mysqlC.MappedPort(ctx, "3306")
if err != nil {
t.Fatal(err)
}
tests := []struct {
name string
connectionString string
want []byte // JSON string
wantErr bool
}{
{
name: "valid Mysql connection",
connectionString: fmt.Sprintf(`root:%s@%s:%s/%s`, mysqlPass, host, port.Port(), mysqlDatabase),
want: expectedOutput,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := Analyzer{Cfg: &config.Config{}}
got, err := a.Analyze(context.Background(), map[string]string{"connection_string": tt.connectionString})
if (err != nil) != tt.wantErr {
t.Errorf("Analyzer.Analyze() error = %v, wantErr %v", err, tt.wantErr)
return
}
// Marshal the actual result to JSON
gotJSON, err := json.Marshal(got)
if err != nil {
t.Fatalf("could not marshal got to JSON: %s", err)
}
// Parse the expected JSON string
var wantObj analyzers.AnalyzerResult
if err := json.Unmarshal(tt.want, &wantObj); err != nil {
t.Fatalf("could not unmarshal want JSON string: %s", err)
}
// Marshal the expected result to JSON (to normalize)
wantJSON, err := json.Marshal(wantObj)
if err != nil {
t.Fatalf("could not marshal want to JSON: %s", err)
}
// Compare bindings separately because they are not guaranteed to be in the same order
if len(got.Bindings) != len(wantObj.Bindings) {
t.Errorf("Analyzer.Analyze() = %s, want %s", gotJSON, wantJSON)
return
}
got.Bindings = nil
wantObj.Bindings = nil
// Compare the rest of the Object
if diff := cmp.Diff(&wantObj, got); diff != "" {
t.Errorf("%s: (-want +got)\n%s", tt.name, diff)
return
}
})
}
}

View file

@ -0,0 +1,451 @@
// Code generated by go generate; DO NOT EDIT.
package mysql
import "errors"
type Permission int
const (
Invalid Permission = iota
Alter Permission = iota
AlterRoutine Permission = iota
AllowNonexistentDefiner Permission = iota
ApplicationPasswordAdmin Permission = iota
AuditAbortExempt Permission = iota
AuditAdmin Permission = iota
AuthenticationPolicyAdmin Permission = iota
BackupAdmin Permission = iota
BinlogAdmin Permission = iota
BinlogEncryptionAdmin Permission = iota
CloneAdmin Permission = iota
ConnectionAdmin Permission = iota
Create Permission = iota
CreateRole Permission = iota
CreateRoutine Permission = iota
CreateTablespace Permission = iota
CreateTemporaryTables Permission = iota
CreateUser Permission = iota
CreateView Permission = iota
Delete Permission = iota
Drop Permission = iota
DropRole Permission = iota
EncryptionKeyAdmin Permission = iota
Event Permission = iota
Execute Permission = iota
File Permission = iota
FirewallAdmin Permission = iota
FirewallExempt Permission = iota
FirewallUser Permission = iota
FlushOptimizerCosts Permission = iota
FlushStatus Permission = iota
FlushTables Permission = iota
FlushUserResources Permission = iota
GrantOption Permission = iota
GroupReplicationAdmin Permission = iota
GroupReplicationStream Permission = iota
Index Permission = iota
InnodbRedoLogArchive Permission = iota
InnodbRedoLogEnable Permission = iota
Insert Permission = iota
LockingTables Permission = iota
MaskingDictionariesAdmin Permission = iota
NdbStoredUser Permission = iota
PasswordlessUserAdmin Permission = iota
PersistRoVariablesAdmin Permission = iota
Process Permission = iota
Proxy Permission = iota
References Permission = iota
Reload Permission = iota
ReplicationApplier Permission = iota
ReplicationClient Permission = iota
ReplicationSlave Permission = iota
ReplicationSlaveAdmin Permission = iota
ResourceGroupAdmin Permission = iota
ResourceGroupUser Permission = iota
RoleAdmin Permission = iota
Select Permission = iota
SensitiveVariablesObserver Permission = iota
ServiceConnectionAdmin Permission = iota
SessionVariablesAdmin Permission = iota
SetAnyDefiner Permission = iota
SetUserId Permission = iota
ShowDatabases Permission = iota
ShowRoutine Permission = iota
ShowView Permission = iota
Shutdown Permission = iota
SkipQueryRewrite Permission = iota
Super Permission = iota
SystemUser Permission = iota
SystemVariablesAdmin Permission = iota
TableEncryptionAdmin Permission = iota
TelemetryLogAdmin Permission = iota
TpConnectionAdmin Permission = iota
TransactionGtidTag Permission = iota
Trigger Permission = iota
Update Permission = iota
Usage Permission = iota
VersionTokenAdmin Permission = iota
XaRecoverAdmin Permission = iota
)
var (
PermissionStrings = map[Permission]string{
Alter: "alter",
AlterRoutine: "alter_routine",
AllowNonexistentDefiner: "allow_nonexistent_definer",
ApplicationPasswordAdmin: "application_password_admin",
AuditAbortExempt: "audit_abort_exempt",
AuditAdmin: "audit_admin",
AuthenticationPolicyAdmin: "authentication_policy_admin",
BackupAdmin: "backup_admin",
BinlogAdmin: "binlog_admin",
BinlogEncryptionAdmin: "binlog_encryption_admin",
CloneAdmin: "clone_admin",
ConnectionAdmin: "connection_admin",
Create: "create",
CreateRole: "create_role",
CreateRoutine: "create_routine",
CreateTablespace: "create_tablespace",
CreateTemporaryTables: "create_temporary_tables",
CreateUser: "create_user",
CreateView: "create_view",
Delete: "delete",
Drop: "drop",
DropRole: "drop_role",
EncryptionKeyAdmin: "encryption_key_admin",
Event: "event",
Execute: "execute",
File: "file",
FirewallAdmin: "firewall_admin",
FirewallExempt: "firewall_exempt",
FirewallUser: "firewall_user",
FlushOptimizerCosts: "flush_optimizer_costs",
FlushStatus: "flush_status",
FlushTables: "flush_tables",
FlushUserResources: "flush_user_resources",
GrantOption: "grant_option",
GroupReplicationAdmin: "group_replication_admin",
GroupReplicationStream: "group_replication_stream",
Index: "index",
InnodbRedoLogArchive: "innodb_redo_log_archive",
InnodbRedoLogEnable: "innodb_redo_log_enable",
Insert: "insert",
LockingTables: "locking_tables",
MaskingDictionariesAdmin: "masking_dictionaries_admin",
NdbStoredUser: "ndb_stored_user",
PasswordlessUserAdmin: "passwordless_user_admin",
PersistRoVariablesAdmin: "persist_ro_variables_admin",
Process: "process",
Proxy: "proxy",
References: "references",
Reload: "reload",
ReplicationApplier: "replication_applier",
ReplicationClient: "replication_client",
ReplicationSlave: "replication_slave",
ReplicationSlaveAdmin: "replication_slave_admin",
ResourceGroupAdmin: "resource_group_admin",
ResourceGroupUser: "resource_group_user",
RoleAdmin: "role_admin",
Select: "select",
SensitiveVariablesObserver: "sensitive_variables_observer",
ServiceConnectionAdmin: "service_connection_admin",
SessionVariablesAdmin: "session_variables_admin",
SetAnyDefiner: "set_any_definer",
SetUserId: "set_user_id",
ShowDatabases: "show_databases",
ShowRoutine: "show_routine",
ShowView: "show_view",
Shutdown: "shutdown",
SkipQueryRewrite: "skip_query_rewrite",
Super: "super",
SystemUser: "system_user",
SystemVariablesAdmin: "system_variables_admin",
TableEncryptionAdmin: "table_encryption_admin",
TelemetryLogAdmin: "telemetry_log_admin",
TpConnectionAdmin: "tp_connection_admin",
TransactionGtidTag: "transaction_gtid_tag",
Trigger: "trigger",
Update: "update",
Usage: "usage",
VersionTokenAdmin: "version_token_admin",
XaRecoverAdmin: "xa_recover_admin",
}
StringToPermission = map[string]Permission{
"alter": Alter,
"alter_routine": AlterRoutine,
"allow_nonexistent_definer": AllowNonexistentDefiner,
"application_password_admin": ApplicationPasswordAdmin,
"audit_abort_exempt": AuditAbortExempt,
"audit_admin": AuditAdmin,
"authentication_policy_admin": AuthenticationPolicyAdmin,
"backup_admin": BackupAdmin,
"binlog_admin": BinlogAdmin,
"binlog_encryption_admin": BinlogEncryptionAdmin,
"clone_admin": CloneAdmin,
"connection_admin": ConnectionAdmin,
"create": Create,
"create_role": CreateRole,
"create_routine": CreateRoutine,
"create_tablespace": CreateTablespace,
"create_temporary_tables": CreateTemporaryTables,
"create_user": CreateUser,
"create_view": CreateView,
"delete": Delete,
"drop": Drop,
"drop_role": DropRole,
"encryption_key_admin": EncryptionKeyAdmin,
"event": Event,
"execute": Execute,
"file": File,
"firewall_admin": FirewallAdmin,
"firewall_exempt": FirewallExempt,
"firewall_user": FirewallUser,
"flush_optimizer_costs": FlushOptimizerCosts,
"flush_status": FlushStatus,
"flush_tables": FlushTables,
"flush_user_resources": FlushUserResources,
"grant_option": GrantOption,
"group_replication_admin": GroupReplicationAdmin,
"group_replication_stream": GroupReplicationStream,
"index": Index,
"innodb_redo_log_archive": InnodbRedoLogArchive,
"innodb_redo_log_enable": InnodbRedoLogEnable,
"insert": Insert,
"locking_tables": LockingTables,
"masking_dictionaries_admin": MaskingDictionariesAdmin,
"ndb_stored_user": NdbStoredUser,
"passwordless_user_admin": PasswordlessUserAdmin,
"persist_ro_variables_admin": PersistRoVariablesAdmin,
"process": Process,
"proxy": Proxy,
"references": References,
"reload": Reload,
"replication_applier": ReplicationApplier,
"replication_client": ReplicationClient,
"replication_slave": ReplicationSlave,
"replication_slave_admin": ReplicationSlaveAdmin,
"resource_group_admin": ResourceGroupAdmin,
"resource_group_user": ResourceGroupUser,
"role_admin": RoleAdmin,
"select": Select,
"sensitive_variables_observer": SensitiveVariablesObserver,
"service_connection_admin": ServiceConnectionAdmin,
"session_variables_admin": SessionVariablesAdmin,
"set_any_definer": SetAnyDefiner,
"set_user_id": SetUserId,
"show_databases": ShowDatabases,
"show_routine": ShowRoutine,
"show_view": ShowView,
"shutdown": Shutdown,
"skip_query_rewrite": SkipQueryRewrite,
"super": Super,
"system_user": SystemUser,
"system_variables_admin": SystemVariablesAdmin,
"table_encryption_admin": TableEncryptionAdmin,
"telemetry_log_admin": TelemetryLogAdmin,
"tp_connection_admin": TpConnectionAdmin,
"transaction_gtid_tag": TransactionGtidTag,
"trigger": Trigger,
"update": Update,
"usage": Usage,
"version_token_admin": VersionTokenAdmin,
"xa_recover_admin": XaRecoverAdmin,
}
PermissionIDs = map[Permission]int{
Alter: 1,
AlterRoutine: 2,
AllowNonexistentDefiner: 3,
ApplicationPasswordAdmin: 4,
AuditAbortExempt: 5,
AuditAdmin: 6,
AuthenticationPolicyAdmin: 7,
BackupAdmin: 8,
BinlogAdmin: 9,
BinlogEncryptionAdmin: 10,
CloneAdmin: 11,
ConnectionAdmin: 12,
Create: 13,
CreateRole: 14,
CreateRoutine: 15,
CreateTablespace: 16,
CreateTemporaryTables: 17,
CreateUser: 18,
CreateView: 19,
Delete: 20,
Drop: 21,
DropRole: 22,
EncryptionKeyAdmin: 23,
Event: 24,
Execute: 25,
File: 26,
FirewallAdmin: 27,
FirewallExempt: 28,
FirewallUser: 29,
FlushOptimizerCosts: 30,
FlushStatus: 31,
FlushTables: 32,
FlushUserResources: 33,
GrantOption: 34,
GroupReplicationAdmin: 35,
GroupReplicationStream: 36,
Index: 37,
InnodbRedoLogArchive: 38,
InnodbRedoLogEnable: 39,
Insert: 40,
LockingTables: 41,
MaskingDictionariesAdmin: 42,
NdbStoredUser: 43,
PasswordlessUserAdmin: 44,
PersistRoVariablesAdmin: 45,
Process: 46,
Proxy: 47,
References: 48,
Reload: 49,
ReplicationApplier: 50,
ReplicationClient: 51,
ReplicationSlave: 52,
ReplicationSlaveAdmin: 53,
ResourceGroupAdmin: 54,
ResourceGroupUser: 55,
RoleAdmin: 56,
Select: 57,
SensitiveVariablesObserver: 58,
ServiceConnectionAdmin: 59,
SessionVariablesAdmin: 60,
SetAnyDefiner: 61,
SetUserId: 62,
ShowDatabases: 63,
ShowRoutine: 64,
ShowView: 65,
Shutdown: 66,
SkipQueryRewrite: 67,
Super: 68,
SystemUser: 69,
SystemVariablesAdmin: 70,
TableEncryptionAdmin: 71,
TelemetryLogAdmin: 72,
TpConnectionAdmin: 73,
TransactionGtidTag: 74,
Trigger: 75,
Update: 76,
Usage: 77,
VersionTokenAdmin: 78,
XaRecoverAdmin: 79,
}
IdToPermission = map[int]Permission{
1: Alter,
2: AlterRoutine,
3: AllowNonexistentDefiner,
4: ApplicationPasswordAdmin,
5: AuditAbortExempt,
6: AuditAdmin,
7: AuthenticationPolicyAdmin,
8: BackupAdmin,
9: BinlogAdmin,
10: BinlogEncryptionAdmin,
11: CloneAdmin,
12: ConnectionAdmin,
13: Create,
14: CreateRole,
15: CreateRoutine,
16: CreateTablespace,
17: CreateTemporaryTables,
18: CreateUser,
19: CreateView,
20: Delete,
21: Drop,
22: DropRole,
23: EncryptionKeyAdmin,
24: Event,
25: Execute,
26: File,
27: FirewallAdmin,
28: FirewallExempt,
29: FirewallUser,
30: FlushOptimizerCosts,
31: FlushStatus,
32: FlushTables,
33: FlushUserResources,
34: GrantOption,
35: GroupReplicationAdmin,
36: GroupReplicationStream,
37: Index,
38: InnodbRedoLogArchive,
39: InnodbRedoLogEnable,
40: Insert,
41: LockingTables,
42: MaskingDictionariesAdmin,
43: NdbStoredUser,
44: PasswordlessUserAdmin,
45: PersistRoVariablesAdmin,
46: Process,
47: Proxy,
48: References,
49: Reload,
50: ReplicationApplier,
51: ReplicationClient,
52: ReplicationSlave,
53: ReplicationSlaveAdmin,
54: ResourceGroupAdmin,
55: ResourceGroupUser,
56: RoleAdmin,
57: Select,
58: SensitiveVariablesObserver,
59: ServiceConnectionAdmin,
60: SessionVariablesAdmin,
61: SetAnyDefiner,
62: SetUserId,
63: ShowDatabases,
64: ShowRoutine,
65: ShowView,
66: Shutdown,
67: SkipQueryRewrite,
68: Super,
69: SystemUser,
70: SystemVariablesAdmin,
71: TableEncryptionAdmin,
72: TelemetryLogAdmin,
73: TpConnectionAdmin,
74: TransactionGtidTag,
75: Trigger,
76: Update,
77: Usage,
78: VersionTokenAdmin,
79: XaRecoverAdmin,
}
)
// ToString converts a Permission enum to its string representation
func (p Permission) ToString() (string, error) {
if str, ok := PermissionStrings[p]; ok {
return str, nil
}
return "", errors.New("invalid permission")
}
// ToID converts a Permission enum to its ID
func (p Permission) ToID() (int, error) {
if id, ok := PermissionIDs[p]; ok {
return id, nil
}
return 0, errors.New("invalid permission")
}
// PermissionFromString converts a string representation to its Permission enum
func PermissionFromString(s string) (Permission, error) {
if p, ok := StringToPermission[s]; ok {
return p, nil
}
return 0, errors.New("invalid permission string")
}
// PermissionFromID converts an ID to its Permission enum
func PermissionFromID(id int) (Permission, error) {
if p, ok := IdToPermission[id]; ok {
return p, nil
}
return 0, errors.New("invalid permission ID")
}

View file

@ -0,0 +1,80 @@
permissions:
- alter
- alter_routine
- allow_nonexistent_definer
- application_password_admin
- audit_abort_exempt
- audit_admin
- authentication_policy_admin
- backup_admin
- binlog_admin
- binlog_encryption_admin
- clone_admin
- connection_admin
- create
- create_role
- create_routine
- create_tablespace
- create_temporary_tables
- create_user
- create_view
- delete
- drop
- drop_role
- encryption_key_admin
- event
- execute
- file
- firewall_admin
- firewall_exempt
- firewall_user
- flush_optimizer_costs
- flush_status
- flush_tables
- flush_user_resources
- grant_option
- group_replication_admin
- group_replication_stream
- index
- innodb_redo_log_archive
- innodb_redo_log_enable
- insert
- locking_tables
- masking_dictionaries_admin
- ndb_stored_user
- passwordless_user_admin
- persist_ro_variables_admin
- process
- proxy
- references
- reload
- replication_applier
- replication_client
- replication_slave
- replication_slave_admin
- resource_group_admin
- resource_group_user
- role_admin
- select
- sensitive_variables_observer
- service_connection_admin
- session_variables_admin
- set_any_definer
- set_user_id
- show_databases
- show_routine
- show_view
- shutdown
- skip_query_rewrite
- super
- system_user
- system_variables_admin
- table_encryption_admin
- telemetry_log_admin
- tp_connection_admin
- transaction_gtid_tag
- trigger
- update
- usage
- version_token_admin
- xa_recover_admin

View file

@ -97,6 +97,9 @@ matchLoop:
err = pingRes.err
s.SetVerificationError(err, jdbcConn)
}
s.AnalysisInfo = map[string]string{
"connection_string": jdbcConn,
}
// TODO: specialized redaction
}

View file

@ -134,6 +134,7 @@ func TestJdbc_FromChunk(t *testing.T) {
t.Fatal("no raw secret present")
}
got[i].Raw = nil
got[i].AnalysisInfo = nil
}
if diff := pretty.Compare(got, tt.want); diff != "" {
t.Errorf("Jdbc.FromData() %s diff: (-got +want)\n%s", tt.name, diff)