mirror of
https://github.com/beekeeper-studio/beekeeper-studio.git
synced 2026-03-13 10:12:54 +08:00
- listTables(null) no longer returns []. Uses buildSchemaFilter() to optionally filter by schema, matching the PostgreSQL driver pattern. - SSL/TLS connections now work. Certificate files (CA, cert, key) are read and passed to trino-client. When no certs are provided, rejectUnauthorized defaults to false (trust server cert). - Removed server:ssl from Trino disabledFeatures so the SSL toggle appears in the connection form. - URL parser now auto-enables ssl for https:// URLs. - Added integration tests for listTables and SSL (with HTTPS-enabled Trino testcontainer). - Added unit tests for SSL config propagation. - Updated Trino connection docs (EN + ES) with SSL section.
This commit is contained in:
committed by
Day Matchullis
parent
7618aa6e63
commit
ab89dcaa67
@@ -1,10 +1,12 @@
|
||||
import rawLog from "@bksLogger"
|
||||
import { readFileSync } from "fs"
|
||||
import { IDbConnectionDatabase } from "@/lib/db/types"
|
||||
import {
|
||||
Trino as TrinoNodeClient,
|
||||
BasicAuth,
|
||||
QueryResult,
|
||||
ConnectionOptions as TrinoConnectionOptions
|
||||
ConnectionOptions as TrinoConnectionOptions,
|
||||
SecureContextOptions
|
||||
} from 'trino-client'
|
||||
import {
|
||||
BaseQueryResult,
|
||||
@@ -41,6 +43,7 @@ import {
|
||||
createCancelablePromise,
|
||||
joinFilters
|
||||
} from "@/common/utils"
|
||||
import { buildSchemaFilter } from "@/lib/db/clients/utils"
|
||||
import {
|
||||
AlterTableSpec,
|
||||
TableKey
|
||||
@@ -109,8 +112,30 @@ export class TrinoClient extends BasicDatabaseClient<TrinoResult> {
|
||||
catalog: this.database.database
|
||||
}
|
||||
|
||||
// TODO: Add ssl using SecureContextOptions (https://trinodb.github.io/trino-js-client/types/ConnectionOptions.html)
|
||||
|
||||
if (this.server.config.ssl) {
|
||||
const sslOptions: SecureContextOptions = {}
|
||||
|
||||
if (this.server.config.sslCaFile) {
|
||||
sslOptions.ca = readFileSync(this.server.config.sslCaFile)
|
||||
}
|
||||
|
||||
if (this.server.config.sslCertFile) {
|
||||
sslOptions.cert = readFileSync(this.server.config.sslCertFile)
|
||||
}
|
||||
|
||||
if (this.server.config.sslKeyFile) {
|
||||
sslOptions.key = readFileSync(this.server.config.sslKeyFile)
|
||||
}
|
||||
|
||||
if (!sslOptions.key && !sslOptions.ca && !sslOptions.cert) {
|
||||
sslOptions.rejectUnauthorized = false
|
||||
} else {
|
||||
sslOptions.rejectUnauthorized = this.server.config.sslRejectUnauthorized
|
||||
}
|
||||
|
||||
connectionObj.ssl = sslOptions
|
||||
}
|
||||
|
||||
if ((this.server.config.user != null && this.server.config.user !== '') || (this.server.config.password != null && this.server.config.password !== '')) {
|
||||
connectionObj.auth = new BasicAuth(this.server.config.user, this.server.config.password)
|
||||
}
|
||||
@@ -279,8 +304,9 @@ export class TrinoClient extends BasicDatabaseClient<TrinoResult> {
|
||||
|
||||
async listTables(filter?: FilterOptions): Promise<TableOrView[]> {
|
||||
log.info('filters in listTables', filter)
|
||||
if (!filter) return []
|
||||
const sql = `select * from ${this.db}.information_schema.tables`
|
||||
const schemaFilter = buildSchemaFilter(filter, 'table_schema')
|
||||
const whereClause = schemaFilter ? `WHERE ${schemaFilter}` : ''
|
||||
const sql = `select * from ${this.db}.information_schema.tables ${whereClause}`
|
||||
const result = await this.driverExecuteSingle(sql)
|
||||
|
||||
return result.rows.map((row) => ({
|
||||
|
||||
@@ -384,6 +384,10 @@ export class SavedConnection extends DbConnectionBase implements IConnection {
|
||||
this.ssl = true
|
||||
}
|
||||
|
||||
if (cleanedUrl.startsWith('https://')) {
|
||||
this.ssl = true
|
||||
}
|
||||
|
||||
if (parsed.params?.TrustServerCertificate && parsed.params.TrustServerCertificate === 'true') {
|
||||
this.trustServerCertificate = true
|
||||
}
|
||||
|
||||
@@ -215,7 +215,6 @@ export const CLIENTS: ClientConfig[] = [
|
||||
topLevelEntity: 'Catalog',
|
||||
defaultPort: 8080,
|
||||
disabledFeatures: [
|
||||
'server:ssl',
|
||||
'server:socketPath',
|
||||
'cancelQuery', // TODO how to do this?
|
||||
],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Network} from "testcontainers"
|
||||
import { DBTestUtil, dbtimeout } from "../../../../lib/db"
|
||||
import { PostgresTestDriver, TrinoTestDriver } from './trino/container'
|
||||
import { TrinoBackingPostgresDriver, TrinoHttpDriver, TrinoHttpsDriver } from './trino/container'
|
||||
import { TableOrView } from "@/lib/db/models"
|
||||
// import { runCommonTests, runReadOnlyTests } from "./all"
|
||||
|
||||
@@ -20,30 +20,30 @@ function testWith(dockerTag: TestVersion, socket = false, readonly = false) {
|
||||
beforeAll(async () => {
|
||||
const network = await new Network().start()
|
||||
|
||||
await PostgresTestDriver.start(dockerTag, socket, readonly, network)
|
||||
await TrinoBackingPostgresDriver.start(dockerTag, socket, readonly, network)
|
||||
|
||||
dbfeeder = new DBTestUtil(PostgresTestDriver.config, "banana", PostgresTestDriver.utilOptions)
|
||||
dbfeeder = new DBTestUtil(TrinoBackingPostgresDriver.config, "banana", TrinoBackingPostgresDriver.utilOptions)
|
||||
await dbfeeder.setupdb()
|
||||
|
||||
// now set up the trino container
|
||||
await TrinoTestDriver.start(dockerTag, readonly, network)
|
||||
await TrinoHttpDriver.start(dockerTag, readonly, network)
|
||||
|
||||
util = new DBTestUtil(TrinoTestDriver.config, 'postgresql', { dialect: 'trino' })
|
||||
util = new DBTestUtil(TrinoHttpDriver.config, 'postgresql', { dialect: 'trino' })
|
||||
await util.connection.connect()
|
||||
|
||||
// Trino uses catalogs instead of databases, access PostgreSQL through 'postgresql' catalog
|
||||
// util = new DBTestUtil(TrinoTestDriver.config, "postgresql", TrinoTestDriver.utilOptions)
|
||||
// util = new DBTestUtil(TrinoHttpDriver.config, "postgresql", TrinoHttpDriver.utilOptions)
|
||||
|
||||
// await util.setupdb()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
// await util.disconnect()
|
||||
await TrinoTestDriver.stop()
|
||||
await dbfeeder.disconnect()
|
||||
if (util.connection) {
|
||||
await util.connection.disconnect()
|
||||
}
|
||||
await TrinoHttpDriver.stop()
|
||||
await dbfeeder.disconnect()
|
||||
await TrinoBackingPostgresDriver.stop()
|
||||
})
|
||||
|
||||
describe("Read Operations", () => {
|
||||
@@ -57,9 +57,14 @@ function testWith(dockerTag: TestVersion, socket = false, readonly = false) {
|
||||
expect(tableNames).toContain('jobs')
|
||||
})
|
||||
|
||||
it("List tables should return empty array when filter is undefined", async () => {
|
||||
const tables: TableOrView[] = await util.connection.listTables()
|
||||
expect(tables).toEqual([])
|
||||
it("List tables should return tables when filter is null (bug #3947)", async () => {
|
||||
const tables: TableOrView[] = await util.connection.listTables(null)
|
||||
expect(tables.length).toBeGreaterThanOrEqual(3)
|
||||
})
|
||||
|
||||
it("List tables should only return tables matching the schema filter", async () => {
|
||||
const tables: TableOrView[] = await util.connection.listTables({ schema: 'public' })
|
||||
tables.forEach(t => expect(t.schema).toBe('public'))
|
||||
})
|
||||
|
||||
it("List table columns should work", async () => {
|
||||
@@ -257,6 +262,62 @@ function testWith(dockerTag: TestVersion, socket = false, readonly = false) {
|
||||
|
||||
TEST_VERSIONS.forEach(({ version, socket, readonly }) => testWith(version, socket, readonly))
|
||||
|
||||
describe('Trino SSL connection (bug #3695)', () => {
|
||||
jest.setTimeout(dbtimeout)
|
||||
|
||||
// Separate instance to avoid mutating the shared TrinoBackingPostgresDriver singleton
|
||||
const sslPgDriver = Object.create(TrinoBackingPostgresDriver, {
|
||||
container: { value: null, writable: true },
|
||||
config: { value: null, writable: true },
|
||||
utilOptions: { value: null, writable: true },
|
||||
})
|
||||
let dbfeeder: DBTestUtil
|
||||
let util: DBTestUtil
|
||||
|
||||
beforeAll(async () => {
|
||||
const network = await new Network().start()
|
||||
|
||||
await sslPgDriver.start('latest', false, false, network)
|
||||
|
||||
dbfeeder = new DBTestUtil(sslPgDriver.config, "banana", sslPgDriver.utilOptions)
|
||||
await dbfeeder.setupdb()
|
||||
|
||||
await TrinoHttpsDriver.start('latest', false, network)
|
||||
|
||||
util = new DBTestUtil(TrinoHttpsDriver.config, 'postgresql', { dialect: 'trino' })
|
||||
await util.connection.connect()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
if (util?.connection) {
|
||||
await util.connection.disconnect()
|
||||
}
|
||||
await TrinoHttpsDriver.stop()
|
||||
await dbfeeder.disconnect()
|
||||
await sslPgDriver.container?.stop()
|
||||
})
|
||||
|
||||
it("Should connect to Trino over HTTPS with ssl=true and CA cert", async () => {
|
||||
const version = await util.connection.versionString()
|
||||
expect(version).toBeDefined()
|
||||
expect(typeof version).toBe('string')
|
||||
expect(version.length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it("Should be able to list tables over SSL", async () => {
|
||||
const tables: TableOrView[] = await util.connection.listTables({ schema: 'public' })
|
||||
const tableNames = tables.map(t => t.name)
|
||||
expect(tables.length).toBeGreaterThanOrEqual(3)
|
||||
expect(tableNames).toContain('people')
|
||||
})
|
||||
|
||||
it("Should be able to query data over SSL", async () => {
|
||||
const result = await util.connection.selectTop('people', 0, 10, [], [], 'public', [])
|
||||
expect(result.result).toBeDefined()
|
||||
expect(Array.isArray(result.result)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
// Additional util.connection tests
|
||||
describe('Trino util.Connection Edge Cases', () => {
|
||||
jest.setTimeout(dbtimeout)
|
||||
|
||||
@@ -4,9 +4,10 @@ import { GenericContainer, Wait, StartedTestContainer } from "testcontainers";
|
||||
import path from 'path'
|
||||
import os from 'os'
|
||||
import fs from 'fs'
|
||||
import { execSync } from 'child_process'
|
||||
import { IDbConnectionServerConfig } from "@/lib/db/types";
|
||||
|
||||
export const PostgresTestDriver = {
|
||||
export const TrinoBackingPostgresDriver = {
|
||||
container: null,
|
||||
utilOptions: null,
|
||||
config: null,
|
||||
@@ -87,7 +88,7 @@ export const PostgresTestDriver = {
|
||||
}
|
||||
}
|
||||
|
||||
export const TrinoTestDriver = {
|
||||
export const TrinoHttpDriver = {
|
||||
container: null as StartedTestContainer | null,
|
||||
pgContainer: null as StartedTestContainer | null,
|
||||
utilOptions: null as Options | null,
|
||||
@@ -146,3 +147,116 @@ connection-password=example`;
|
||||
await this.container?.stop()
|
||||
}
|
||||
}
|
||||
|
||||
function generateTrinoSslFiles(tempDir: string) {
|
||||
const certDir = path.join(tempDir, 'certs')
|
||||
fs.mkdirSync(certDir, { recursive: true })
|
||||
|
||||
const keyFile = path.join(certDir, 'trino.key')
|
||||
const certFile = path.join(certDir, 'trino.crt')
|
||||
const p12File = path.join(certDir, 'trino.p12')
|
||||
const keystorePassword = 'trinopass'
|
||||
|
||||
// Generate self-signed cert and private key
|
||||
execSync(
|
||||
`openssl req -x509 -newkey rsa:2048 -keyout ${keyFile} -out ${certFile} ` +
|
||||
`-days 1 -nodes -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"`,
|
||||
{ stdio: 'pipe' }
|
||||
)
|
||||
|
||||
// Convert to PKCS12 keystore for Trino's Java TLS
|
||||
execSync(
|
||||
`openssl pkcs12 -export -in ${certFile} -inkey ${keyFile} ` +
|
||||
`-out ${p12File} -passout pass:${keystorePassword}`,
|
||||
{ stdio: 'pipe' }
|
||||
)
|
||||
|
||||
return { keyFile, certFile, p12File, keystorePassword, certDir }
|
||||
}
|
||||
|
||||
export const TrinoHttpsDriver = {
|
||||
container: null as StartedTestContainer | null,
|
||||
config: null as IDbConnectionServerConfig | null,
|
||||
certFile: null as string | null,
|
||||
|
||||
async start(dockerTag: string, readonly: boolean, network) {
|
||||
const startupTimeout = dbtimeout * 2
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'trino-ssl-'))
|
||||
|
||||
// Generate SSL certs and keystore
|
||||
const ssl = generateTrinoSslFiles(tempDir)
|
||||
this.certFile = ssl.certFile
|
||||
|
||||
// Create catalog config for postgresql connector
|
||||
const catalogDir = path.join(tempDir, 'catalog')
|
||||
fs.mkdirSync(catalogDir)
|
||||
fs.writeFileSync(
|
||||
path.join(catalogDir, 'postgresql.properties'),
|
||||
`connector.name=postgresql
|
||||
connection-url=jdbc:postgresql://postgres:5432/banana
|
||||
connection-user=postgres
|
||||
connection-password=example`
|
||||
)
|
||||
|
||||
// Generate a shared secret for internal communication
|
||||
const sharedSecret = require('crypto').randomBytes(64).toString('base64')
|
||||
|
||||
// Shell script to merge SSL settings into the existing config.properties,
|
||||
// then start Trino. This preserves default properties like catalog.management.
|
||||
const entrypointScript = path.join(tempDir, 'entrypoint.sh')
|
||||
fs.writeFileSync(entrypointScript, [
|
||||
'#!/bin/bash',
|
||||
'set -e',
|
||||
"sed -i '/^http-server.http.port=/d' /etc/trino/config.properties",
|
||||
"sed -i '/^discovery.uri=/d' /etc/trino/config.properties",
|
||||
`cat >> /etc/trino/config.properties << 'SSLEOF'`,
|
||||
'http-server.http.enabled=false',
|
||||
'http-server.https.enabled=true',
|
||||
'http-server.https.port=8443',
|
||||
`http-server.https.keystore.path=/etc/trino/certs/trino.p12`,
|
||||
`http-server.https.keystore.key=${ssl.keystorePassword}`,
|
||||
'discovery.uri=https://localhost:8443',
|
||||
'internal-communication.https.required=true',
|
||||
`internal-communication.shared-secret=${sharedSecret}`,
|
||||
'SSLEOF',
|
||||
'exec /usr/lib/trino/bin/run-trino',
|
||||
].join('\n'))
|
||||
fs.chmodSync(entrypointScript, '755')
|
||||
|
||||
this.container = await new GenericContainer(`trinodb/trino:${dockerTag}`)
|
||||
.withNetwork(network)
|
||||
.withExposedPorts(8443)
|
||||
.withBindMounts([
|
||||
{ source: catalogDir, target: '/etc/trino/catalog', mode: 'ro' },
|
||||
{ source: ssl.certDir, target: '/etc/trino/certs', mode: 'ro' },
|
||||
{ source: entrypointScript, target: '/etc/trino/entrypoint.sh', mode: 'ro' },
|
||||
])
|
||||
.withCommand(['/etc/trino/entrypoint.sh'])
|
||||
.withWaitStrategy(Wait.forLogMessage("SERVER STARTED"))
|
||||
.withStartupTimeout(startupTimeout)
|
||||
.start()
|
||||
|
||||
this.config = {
|
||||
client: 'trino',
|
||||
host: this.container.getHost(),
|
||||
port: this.container.getMappedPort(8443),
|
||||
user: 'test',
|
||||
password: null,
|
||||
osUser: 'foo',
|
||||
ssh: null,
|
||||
sslCaFile: ssl.certFile,
|
||||
sslCertFile: null,
|
||||
sslKeyFile: null,
|
||||
sslRejectUnauthorized: false,
|
||||
ssl: true,
|
||||
domain: null,
|
||||
socketPath: null,
|
||||
socketPathEnabled: false,
|
||||
readOnlyMode: readonly,
|
||||
}
|
||||
},
|
||||
|
||||
async stop() {
|
||||
await this.container?.stop()
|
||||
},
|
||||
}
|
||||
|
||||
141
apps/studio/tests/unit/lib/db/clients/trino.spec.ts
Normal file
141
apps/studio/tests/unit/lib/db/clients/trino.spec.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
jest.mock('trino-client', () => {
|
||||
const mockQuery = jest.fn().mockResolvedValue({
|
||||
[Symbol.asyncIterator]: async function* () {
|
||||
yield {
|
||||
data: [['1.0.0']],
|
||||
columns: [{ name: '_col0', type: 'varchar' }]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
Trino: {
|
||||
create: jest.fn().mockReturnValue({ query: mockQuery })
|
||||
},
|
||||
BasicAuth: jest.fn().mockImplementation((user, pass) => ({ type: 'basic', username: user, password: pass })),
|
||||
}
|
||||
})
|
||||
|
||||
import fs from 'fs'
|
||||
import os from 'os'
|
||||
import path from 'path'
|
||||
import { Trino as TrinoNodeClient } from 'trino-client'
|
||||
import { TrinoClient } from '@commercial/backend/lib/db/clients/trino'
|
||||
import { IDbConnectionServer } from '@/lib/db/backendTypes'
|
||||
import { IDbConnectionDatabase } from '@/lib/db/types'
|
||||
|
||||
function makeServer(overrides: Partial<IDbConnectionServer['config']> = {}): IDbConnectionServer {
|
||||
return {
|
||||
db: {},
|
||||
config: {
|
||||
client: 'trino',
|
||||
host: 'localhost',
|
||||
port: 8080,
|
||||
user: 'testuser',
|
||||
password: null,
|
||||
readOnlyMode: false,
|
||||
osUser: 'testuser',
|
||||
ssh: null,
|
||||
sslCaFile: null,
|
||||
sslCertFile: null,
|
||||
sslKeyFile: null,
|
||||
sslRejectUnauthorized: false,
|
||||
ssl: false,
|
||||
domain: null,
|
||||
socketPath: null,
|
||||
socketPathEnabled: false,
|
||||
...overrides,
|
||||
},
|
||||
} as IDbConnectionServer
|
||||
}
|
||||
|
||||
function makeDatabase(): IDbConnectionDatabase {
|
||||
return {
|
||||
database: 'postgresql',
|
||||
connected: false,
|
||||
connecting: false,
|
||||
namespace: null,
|
||||
}
|
||||
}
|
||||
|
||||
describe('TrinoClient SSL configuration (bug #3695)', () => {
|
||||
let tmpDir: string
|
||||
let caFile: string
|
||||
let certFile: string
|
||||
let keyFile: string
|
||||
|
||||
beforeAll(() => {
|
||||
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'trino-test-'))
|
||||
caFile = path.join(tmpDir, 'ca.pem')
|
||||
certFile = path.join(tmpDir, 'cert.pem')
|
||||
keyFile = path.join(tmpDir, 'key.pem')
|
||||
fs.writeFileSync(caFile, 'fake-ca')
|
||||
fs.writeFileSync(certFile, 'fake-cert')
|
||||
fs.writeFileSync(keyFile, 'fake-key')
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
fs.rmSync(tmpDir, { recursive: true })
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should pass ssl options to Trino.create() when ssl is true', async () => {
|
||||
const server = makeServer({ ssl: true })
|
||||
const client = new TrinoClient(server, makeDatabase())
|
||||
await client.connect()
|
||||
|
||||
const createCall = (TrinoNodeClient.create as jest.Mock).mock.calls[0][0]
|
||||
expect(createCall.ssl).toBeDefined()
|
||||
})
|
||||
|
||||
it('should use https protocol when ssl is true', async () => {
|
||||
const server = makeServer({ ssl: true })
|
||||
const client = new TrinoClient(server, makeDatabase())
|
||||
await client.connect()
|
||||
|
||||
const createCall = (TrinoNodeClient.create as jest.Mock).mock.calls[0][0]
|
||||
expect(createCall.server).toContain('https')
|
||||
})
|
||||
|
||||
it('should pass ssl cert/key/ca files when configured', async () => {
|
||||
const server = makeServer({
|
||||
ssl: true,
|
||||
sslCaFile: caFile,
|
||||
sslCertFile: certFile,
|
||||
sslKeyFile: keyFile,
|
||||
})
|
||||
const client = new TrinoClient(server, makeDatabase())
|
||||
await client.connect()
|
||||
|
||||
const createCall = (TrinoNodeClient.create as jest.Mock).mock.calls[0][0]
|
||||
expect(createCall.ssl).toBeDefined()
|
||||
expect(createCall.ssl.ca).toBeDefined()
|
||||
expect(createCall.ssl.cert).toBeDefined()
|
||||
expect(createCall.ssl.key).toBeDefined()
|
||||
})
|
||||
|
||||
it('should set rejectUnauthorized based on config', async () => {
|
||||
const server = makeServer({
|
||||
ssl: true,
|
||||
sslRejectUnauthorized: false,
|
||||
})
|
||||
const client = new TrinoClient(server, makeDatabase())
|
||||
await client.connect()
|
||||
|
||||
const createCall = (TrinoNodeClient.create as jest.Mock).mock.calls[0][0]
|
||||
expect(createCall.ssl).toBeDefined()
|
||||
expect(createCall.ssl.rejectUnauthorized).toBe(false)
|
||||
})
|
||||
|
||||
it('should not pass ssl options when ssl is false', async () => {
|
||||
const server = makeServer({ ssl: false })
|
||||
const client = new TrinoClient(server, makeDatabase())
|
||||
await client.connect()
|
||||
|
||||
const createCall = (TrinoNodeClient.create as jest.Mock).mock.calls[0][0]
|
||||
expect(createCall.ssl).toBeUndefined()
|
||||
})
|
||||
})
|
||||
@@ -21,11 +21,22 @@ Conectarse a una base de datos Trino desde Beekeeper Studio es sencillo. Selecci
|
||||
Para conectarte a una base de datos Trino, necesitaras la siguiente informacion:
|
||||
|
||||
- **Host**: La direccion IP o nombre de host de tu servidor Trino.
|
||||
- **Puerto**: El puerto predeterminado es 8080, pero esto se puede personalizar si tu servidor usa un puerto diferente.
|
||||
- **Puerto**: El puerto predeterminado es 8080 para HTTP, o 8443 para HTTPS. Esto se puede personalizar si tu servidor usa un puerto diferente.
|
||||
- **Nombre de usuario**: Tu nombre de usuario de Trino, siendo default el valor predeterminado tipico.
|
||||
- **Contrasena**: Tu contrasena de Trino, si aplica.
|
||||
- **Catalogo predeterminado (opcional)**: El catalogo al que quieres conectarte inicialmente al inicio
|
||||
|
||||
### Conexiones SSL / HTTPS
|
||||
|
||||
Si tu coordinador Trino esta configurado con TLS/HTTPS, habilita **SSL** en el formulario de conexion. Beekeeper Studio soporta tres modos de SSL:
|
||||
|
||||
1. **Confiar en el certificado del servidor** — Habilita SSL sin proporcionar archivos de certificado. Beekeeper Studio se conectara por HTTPS pero no verificara el certificado del servidor. Esta es la opcion mas sencilla y funciona con certificados autofirmados.
|
||||
2. **Proporcionar un certificado CA** — Si tu servidor Trino usa un certificado firmado por una CA privada, proporciona el archivo de certificado CA. Deja "Rechazar no autorizados" desmarcado para permitir la conexion.
|
||||
3. **Verificacion completa de certificados** — Proporciona el certificado CA y opcionalmente un certificado de cliente y archivo de clave, luego marca "Rechazar no autorizados" para aplicar la verificacion TLS completa.
|
||||
|
||||
!!! tip
|
||||
Si importas una URL de conexion que comienza con `https://`, SSL se habilitara automaticamente.
|
||||
|
||||
### Probar tu conexion de Trino
|
||||
|
||||
Antes de guardar los detalles de tu conexion, Beekeeper Studio te permite probar la conexion:
|
||||
@@ -40,6 +51,7 @@ Una vez que los detalles de tu conexion han sido verificados, puedes elegir guar
|
||||
|
||||
## Funciones soportadas
|
||||
|
||||
- Conexiones SSL / HTTPS (con archivos opcionales de CA, certificado de cliente y clave)
|
||||
- Vista de datos de tabla
|
||||
- Ordenamiento y filtrado de datos de tabla
|
||||
- Vista de estructura de tabla
|
||||
|
||||
@@ -21,11 +21,22 @@ Connecting to a Trino database from Beekeeper Studio is straightforward. SElect
|
||||
To connect to a Trino database, you'll need the following information:
|
||||
|
||||
- **Host**: The IP address or hostname of your Trino server.
|
||||
- **Port**: The default port is 8080, but this can be customized if your server uses a different port.
|
||||
- **Port**: The default port is 8080 for HTTP, or 8443 for HTTPS. This can be customized if your server uses a different port.
|
||||
- **Username**: Your Trino username, with default being the typical default.
|
||||
- **Password**: Your Trino password, if applicable.
|
||||
- **Default Catalog (optional)**: The catalog you want initially connected to at startup
|
||||
|
||||
### SSL / HTTPS Connections
|
||||
|
||||
If your Trino coordinator is configured with TLS/HTTPS, enable **SSL** in the connection form. Beekeeper Studio supports three SSL modes:
|
||||
|
||||
1. **Trust the server certificate** — Enable SSL without providing any certificate files. Beekeeper Studio will connect over HTTPS but will not verify the server's certificate. This is the simplest option and works with self-signed certificates.
|
||||
2. **Provide a CA certificate** — If your Trino server uses a certificate signed by a private CA, provide the CA certificate file. Leave "Reject Unauthorized" unchecked to allow the connection.
|
||||
3. **Full certificate verification** — Provide the CA certificate and optionally a client certificate and key file, then check "Reject Unauthorized" to enforce full TLS verification.
|
||||
|
||||
!!! tip
|
||||
If you import a connection URL that starts with `https://`, SSL will be enabled automatically.
|
||||
|
||||
### Testing Your Trino Connection
|
||||
|
||||
Before saving your connection details, Beekeeper Studio allows you to test the connection:
|
||||
@@ -40,6 +51,7 @@ Once your connection details have been verified, you can choose to save them by
|
||||
|
||||
## Supported Features
|
||||
|
||||
- SSL / HTTPS connections (with optional CA, client cert, and key files)
|
||||
- Table data view
|
||||
- Table data sorting, filtering
|
||||
- Table structure view
|
||||
|
||||
Reference in New Issue
Block a user