Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
jobily
Questdb
提交
807fa1fc
Q
Questdb
项目概览
jobily
/
Questdb
12 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
Questdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
807fa1fc
编写于
5月 19, 2020
作者:
P
Patrick Mackinlay
提交者:
GitHub
5月 19, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: questdb can be configured as globally read-only
上级
36754fe3
变更
14
显示空白变更内容
内联
并排
Showing
14 changed file
with
194 addition
and
9 deletion
+194
-9
core/src/main/java/io/questdb/PropServerConfiguration.java
core/src/main/java/io/questdb/PropServerConfiguration.java
+7
-0
core/src/main/java/io/questdb/cairo/CairoEngine.java
core/src/main/java/io/questdb/cairo/CairoEngine.java
+8
-2
core/src/main/java/io/questdb/cairo/CairoSecurityContext.java
.../src/main/java/io/questdb/cairo/CairoSecurityContext.java
+8
-0
core/src/main/java/io/questdb/cairo/pool/ex/EntryUnavailableException.java
...a/io/questdb/cairo/pool/ex/EntryUnavailableException.java
+5
-1
core/src/main/java/io/questdb/cairo/security/AllowAllCairoSecurityContext.java
.../questdb/cairo/security/AllowAllCairoSecurityContext.java
+5
-0
core/src/main/java/io/questdb/cairo/security/ReadOnlyCairoSecurityContext.java
.../questdb/cairo/security/ReadOnlyCairoSecurityContext.java
+12
-0
core/src/main/java/io/questdb/cutlass/http/DefaultHttpServerConfiguration.java
.../questdb/cutlass/http/DefaultHttpServerConfiguration.java
+5
-0
core/src/main/java/io/questdb/cutlass/http/HttpConnectionContext.java
...n/java/io/questdb/cutlass/http/HttpConnectionContext.java
+3
-1
core/src/main/java/io/questdb/cutlass/http/HttpServerConfiguration.java
...java/io/questdb/cutlass/http/HttpServerConfiguration.java
+3
-0
core/src/main/java/io/questdb/griffin/SqlCompiler.java
core/src/main/java/io/questdb/griffin/SqlCompiler.java
+3
-2
core/src/test/java/io/questdb/griffin/AlterTableAddColumnTest.java
...test/java/io/questdb/griffin/AlterTableAddColumnTest.java
+1
-1
core/src/test/java/io/questdb/griffin/AlterTableAlterColumnTest.java
...st/java/io/questdb/griffin/AlterTableAlterColumnTest.java
+1
-1
core/src/test/java/io/questdb/griffin/AlterTableDropColumnTest.java
...est/java/io/questdb/griffin/AlterTableDropColumnTest.java
+1
-1
core/src/test/java/io/questdb/griffin/SecurityTest.java
core/src/test/java/io/questdb/griffin/SecurityTest.java
+132
-0
未找到文件。
core/src/main/java/io/questdb/PropServerConfiguration.java
浏览文件 @
807fa1fc
...
...
@@ -183,6 +183,7 @@ public class PropServerConfiguration implements ServerConfiguration {
private
int
jsonQueryDoubleScale
;
private
int
jsonQueryConnectionCheckFrequency
;
private
boolean
httpFrozenClock
;
private
boolean
readOnlySecurityContext
;
public
PropServerConfiguration
(
String
root
,
Properties
properties
)
throws
ServerConfigurationException
,
JsonException
{
this
.
sharedWorkerCount
=
getInt
(
properties
,
"shared.worker.count"
,
2
);
...
...
@@ -255,6 +256,7 @@ public class PropServerConfiguration implements ServerConfiguration {
this
.
jsonQueryConnectionCheckFrequency
=
getInt
(
properties
,
"http.json.query.connection.check.frequency"
,
1_000_000
);
this
.
jsonQueryFloatScale
=
getInt
(
properties
,
"http.json.query.float.scale"
,
4
);
this
.
jsonQueryDoubleScale
=
getInt
(
properties
,
"http.json.query.double.scale"
,
12
);
this
.
readOnlySecurityContext
=
getBoolean
(
properties
,
"http.security.readonly"
,
false
);
parseBindTo
(
properties
,
"http.bind.to"
,
"0.0.0.0:9000"
,
(
a
,
p
)
->
{
bindIPv4Address
=
a
;
...
...
@@ -865,6 +867,11 @@ public class PropServerConfiguration implements ServerConfiguration {
public
boolean
haltOnError
()
{
return
httpWorkerHaltOnError
;
}
@Override
public
boolean
readOnlySecurityContext
()
{
return
readOnlySecurityContext
;
}
}
private
class
PropCairoConfiguration
implements
CairoConfiguration
{
...
...
core/src/main/java/io/questdb/cairo/CairoEngine.java
浏览文件 @
807fa1fc
...
...
@@ -82,6 +82,7 @@ public class CairoEngine implements Closeable {
Path
path
,
TableStructure
struct
)
{
securityContext
.
checkWritePermission
();
TableUtils
.
createTable
(
configuration
.
getFilesFacade
(),
mem
,
...
...
@@ -155,6 +156,7 @@ public class CairoEngine implements Closeable {
CairoSecurityContext
securityContext
,
CharSequence
tableName
)
{
securityContext
.
checkWritePermission
();
return
writerPool
.
get
(
tableName
);
}
...
...
@@ -163,6 +165,7 @@ public class CairoEngine implements Closeable {
CharSequence
tableName
,
CharSequence
backupDirName
)
{
securityContext
.
checkWritePermission
();
// There is no point in pooling/caching these writers since they are only used once, backups are not incremental
return
new
TableWriter
(
configuration
,
tableName
,
messageBus
,
true
,
DefaultLifecycleManager
.
INSTANCE
,
backupDirName
);
}
...
...
@@ -171,6 +174,7 @@ public class CairoEngine implements Closeable {
CairoSecurityContext
securityContext
,
CharSequence
tableName
)
{
securityContext
.
checkWritePermission
();
if
(
writerPool
.
lock
(
tableName
))
{
boolean
locked
=
readerPool
.
lock
(
tableName
);
if
(
locked
)
{
...
...
@@ -226,6 +230,7 @@ public class CairoEngine implements Closeable {
Path
path
,
CharSequence
tableName
)
{
securityContext
.
checkWritePermission
();
if
(
lock
(
securityContext
,
tableName
))
{
try
{
path
.
of
(
configuration
.
getRoot
()).
concat
(
tableName
).
$
();
...
...
@@ -255,6 +260,7 @@ public class CairoEngine implements Closeable {
Path
otherPath
,
CharSequence
newName
)
{
securityContext
.
checkWritePermission
();
if
(
lock
(
securityContext
,
tableName
))
{
try
{
rename0
(
path
,
tableName
,
otherPath
,
newName
);
...
...
core/src/main/java/io/questdb/cairo/CairoSecurityContext.java
浏览文件 @
807fa1fc
...
...
@@ -25,4 +25,12 @@
package
io.questdb.cairo
;
public
interface
CairoSecurityContext
{
default
void
checkWritePermission
()
{
if
(!
canWrite
())
{
throw
CairoException
.
instance
(
0
).
put
(
"Write permission denied"
);
}
}
boolean
canWrite
();
}
core/src/main/java/io/questdb/cairo/pool/ex/EntryUnavailableException.java
浏览文件 @
807fa1fc
...
...
@@ -27,5 +27,9 @@ package io.questdb.cairo.pool.ex;
import
io.questdb.cairo.CairoException
;
public
class
EntryUnavailableException
extends
CairoException
{
public
static
final
EntryUnavailableException
INSTANCE
=
new
EntryUnavailableException
();
public
static
final
EntryUnavailableException
INSTANCE
;
static
{
INSTANCE
=
new
EntryUnavailableException
();
INSTANCE
.
put
(
"table busy"
);
}
}
core/src/main/java/io/questdb/cairo/security/AllowAllCairoSecurityContext.java
浏览文件 @
807fa1fc
...
...
@@ -28,4 +28,9 @@ import io.questdb.cairo.CairoSecurityContext;
public
class
AllowAllCairoSecurityContext
implements
CairoSecurityContext
{
public
static
final
AllowAllCairoSecurityContext
INSTANCE
=
new
AllowAllCairoSecurityContext
();
@Override
public
boolean
canWrite
()
{
return
true
;
}
}
core/src/main/java/io/questdb/cairo/security/ReadOnlyCairoSecurityContext.java
0 → 100644
浏览文件 @
807fa1fc
package
io.questdb.cairo.security
;
import
io.questdb.cairo.CairoSecurityContext
;
public
class
ReadOnlyCairoSecurityContext
implements
CairoSecurityContext
{
public
static
final
ReadOnlyCairoSecurityContext
INSTANCE
=
new
ReadOnlyCairoSecurityContext
();
@Override
public
boolean
canWrite
()
{
return
false
;
}
}
core/src/main/java/io/questdb/cutlass/http/DefaultHttpServerConfiguration.java
浏览文件 @
807fa1fc
...
...
@@ -209,4 +209,9 @@ class DefaultHttpServerConfiguration implements HttpServerConfiguration {
public
boolean
haltOnError
()
{
return
false
;
}
@Override
public
boolean
readOnlySecurityContext
()
{
return
false
;
}
}
core/src/main/java/io/questdb/cutlass/http/HttpConnectionContext.java
浏览文件 @
807fa1fc
...
...
@@ -26,6 +26,7 @@ package io.questdb.cutlass.http;
import
io.questdb.cairo.CairoSecurityContext
;
import
io.questdb.cairo.security.AllowAllCairoSecurityContext
;
import
io.questdb.cairo.security.ReadOnlyCairoSecurityContext
;
import
io.questdb.log.Log
;
import
io.questdb.log.LogFactory
;
import
io.questdb.network.*
;
...
...
@@ -50,7 +51,7 @@ public class HttpConnectionContext implements IOContext, Locality, Mutable {
private
final
LocalValueMap
localValueMap
=
new
LocalValueMap
();
private
final
NetworkFacade
nf
;
private
final
long
multipartIdleSpinCount
;
private
final
CairoSecurityContext
cairoSecurityContext
=
AllowAllCairoSecurityContext
.
INSTANCE
;
private
final
CairoSecurityContext
cairoSecurityContext
;
private
final
boolean
dumpNetworkTraffic
;
private
final
boolean
allowDeflateBeforeSend
;
private
long
fd
;
...
...
@@ -71,6 +72,7 @@ public class HttpConnectionContext implements IOContext, Locality, Mutable {
this
.
multipartIdleSpinCount
=
configuration
.
getMultipartIdleSpinCount
();
this
.
dumpNetworkTraffic
=
configuration
.
getDumpNetworkTraffic
();
this
.
allowDeflateBeforeSend
=
configuration
.
allowDeflateBeforeSend
();
cairoSecurityContext
=
configuration
.
readOnlySecurityContext
()
?
ReadOnlyCairoSecurityContext
.
INSTANCE
:
AllowAllCairoSecurityContext
.
INSTANCE
;
}
@Override
...
...
core/src/main/java/io/questdb/cutlass/http/HttpServerConfiguration.java
浏览文件 @
807fa1fc
...
...
@@ -61,9 +61,12 @@ public interface HttpServerConfiguration extends WorkerPoolAwareConfiguration {
int
getSendBufferSize
();
@Override
boolean
isEnabled
();
boolean
getDumpNetworkTraffic
();
boolean
allowDeflateBeforeSend
();
boolean
readOnlySecurityContext
();
}
core/src/main/java/io/questdb/griffin/SqlCompiler.java
浏览文件 @
807fa1fc
...
...
@@ -697,8 +697,8 @@ public class SqlCompiler implements Closeable {
throw
SqlException
.
$
(
lexer
.
lastTokenPosition
(),
"'add' or 'drop' expected"
);
}
}
catch
(
CairoException
e
)
{
LOG
.
info
().
$
(
"failed to
lock table for alter
: "
).
$
((
Sinkable
)
e
).
$
();
throw
SqlException
.
$
(
tableNamePosition
,
"table '"
).
put
(
tableName
).
put
(
"'
is busy"
);
LOG
.
info
().
$
(
"failed to
alter table
: "
).
$
((
Sinkable
)
e
).
$
();
throw
SqlException
.
$
(
tableNamePosition
,
"table '"
).
put
(
tableName
).
put
(
"'
cannot be altered: "
).
put
(
e
);
}
return
compiledQuery
.
ofAlter
();
...
...
@@ -1571,6 +1571,7 @@ public class SqlCompiler implements Closeable {
}
private
CompiledQuery
sqlBackup
(
SqlExecutionContext
executionContext
)
throws
SqlException
{
executionContext
.
getCairoSecurityContext
().
checkWritePermission
();
if
(
null
==
configuration
.
getBackupRoot
())
{
throw
CairoException
.
instance
(
0
).
put
(
"Backup is disabled, no backup root directory is configured in the server configuration ['cairo.sql.backup.root' property]"
);
}
...
...
core/src/test/java/io/questdb/griffin/AlterTableAddColumnTest.java
浏览文件 @
807fa1fc
...
...
@@ -90,7 +90,7 @@ public class AlterTableAddColumnTest extends AbstractGriffinTest {
}
}
catch
(
SqlException
e
)
{
Assert
.
assertEquals
(
12
,
e
.
getPosition
());
TestUtils
.
assertContains
(
e
.
getFlyweightMessage
(),
"table 'x'
is
busy"
);
TestUtils
.
assertContains
(
e
.
getFlyweightMessage
(),
"table 'x'
cannot be altered: [0]: table
busy"
);
}
allHaltLatch
.
await
(
2
,
TimeUnit
.
SECONDS
);
...
...
core/src/test/java/io/questdb/griffin/AlterTableAlterColumnTest.java
浏览文件 @
807fa1fc
...
...
@@ -117,7 +117,7 @@ public class AlterTableAlterColumnTest extends AbstractGriffinTest {
}
}
catch
(
SqlException
e
)
{
Assert
.
assertEquals
(
12
,
e
.
getPosition
());
TestUtils
.
assertContains
(
e
.
getFlyweightMessage
(),
"table 'x'
is
busy"
);
TestUtils
.
assertContains
(
e
.
getFlyweightMessage
(),
"table 'x'
cannot be altered: [0]: table
busy"
);
}
allHaltLatch
.
await
(
2
,
TimeUnit
.
SECONDS
);
});
...
...
core/src/test/java/io/questdb/griffin/AlterTableDropColumnTest.java
浏览文件 @
807fa1fc
...
...
@@ -92,7 +92,7 @@ public class AlterTableDropColumnTest extends AbstractGriffinTest {
}
}
catch
(
SqlException
e
)
{
Assert
.
assertEquals
(
12
,
e
.
getPosition
());
TestUtils
.
assertContains
(
e
.
getFlyweightMessage
(),
"table 'x'
is
busy"
);
TestUtils
.
assertContains
(
e
.
getFlyweightMessage
(),
"table 'x'
cannot be altered: [0]: table
busy"
);
}
engine
.
releaseAllReaders
();
...
...
core/src/test/java/io/questdb/griffin/SecurityTest.java
0 → 100644
浏览文件 @
807fa1fc
package
io.questdb.griffin
;
import
org.junit.Assert
;
import
org.junit.Test
;
import
io.questdb.cairo.security.ReadOnlyCairoSecurityContext
;
import
io.questdb.cairo.sql.InsertMethod
;
import
io.questdb.cairo.sql.InsertStatement
;
public
class
SecurityTest
extends
AbstractGriffinTest
{
protected
static
final
SqlExecutionContext
readOnlyExecutionContext
=
new
SqlExecutionContextImpl
(
configuration
,
messageBus
,
1
)
.
with
(
ReadOnlyCairoSecurityContext
.
INSTANCE
,
bindVariableService
,
null
);
@Test
public
void
testCreateTableDeniedOnNoWriteAccess
()
throws
Exception
{
assertMemoryLeak
(()
->
{
try
{
compiler
.
compile
(
"create table balances(cust_id int, ccy symbol, balance double)"
,
readOnlyExecutionContext
);
Assert
.
fail
();
}
catch
(
Exception
ex
)
{
Assert
.
assertTrue
(
ex
.
toString
().
contains
(
"permission denied"
));
}
try
{
assertQuery
(
"count\n1\n"
,
"select count() from balances"
,
null
);
Assert
.
fail
();
}
catch
(
SqlException
ex
)
{
Assert
.
assertTrue
(
ex
.
toString
().
contains
(
"table does not exist"
));
}
});
}
@Test
public
void
testInsertDeniedOnNoWriteAccess
()
throws
Exception
{
assertMemoryLeak
(()
->
{
compiler
.
compile
(
"create table balances(cust_id int, ccy symbol, balance double)"
,
sqlExecutionContext
);
assertQuery
(
"count\n0\n"
,
"select count() from balances"
,
null
);
CompiledQuery
cq
=
compiler
.
compile
(
"insert into balances values (1, 'EUR', 140.6)"
,
sqlExecutionContext
);
InsertStatement
insertStatement
=
cq
.
getInsertStatement
();
try
(
InsertMethod
method
=
insertStatement
.
createMethod
(
sqlExecutionContext
))
{
method
.
execute
();
method
.
commit
();
}
assertQuery
(
"count\n1\n"
,
"select count() from balances"
,
null
);
try
{
cq
=
compiler
.
compile
(
"insert into balances values (2, 'ZAR', 140.6)"
,
readOnlyExecutionContext
);
insertStatement
=
cq
.
getInsertStatement
();
try
(
InsertMethod
method
=
insertStatement
.
createMethod
(
readOnlyExecutionContext
))
{
method
.
execute
();
method
.
commit
();
}
Assert
.
fail
();
}
catch
(
Exception
ex
)
{
Assert
.
assertTrue
(
ex
.
toString
().
contains
(
"permission denied"
));
}
assertQuery
(
"count\n1\n"
,
"select count() from balances"
,
null
);
});
}
@Test
public
void
testDropTableDeniedOnNoWriteAccess
()
throws
Exception
{
assertMemoryLeak
(()
->
{
compiler
.
compile
(
"create table balances(cust_id int, ccy symbol, balance double)"
,
sqlExecutionContext
);
try
{
compiler
.
compile
(
"drop table balances"
,
readOnlyExecutionContext
);
Assert
.
fail
();
}
catch
(
Exception
ex
)
{
Assert
.
assertTrue
(
ex
.
toString
().
contains
(
"permission denied"
));
}
assertQuery
(
"count\n0\n"
,
"select count() from balances"
,
null
);
});
}
@Test
public
void
testAlterTableDeniedOnNoWriteAccess
()
throws
Exception
{
assertMemoryLeak
(()
->
{
compiler
.
compile
(
"create table balances(cust_id int, ccy symbol, balance double)"
,
sqlExecutionContext
);
CompiledQuery
cq
=
compiler
.
compile
(
"insert into balances values (1, 'EUR', 140.6)"
,
sqlExecutionContext
);
InsertStatement
insertStatement
=
cq
.
getInsertStatement
();
try
(
InsertMethod
method
=
insertStatement
.
createMethod
(
sqlExecutionContext
))
{
method
.
execute
();
method
.
commit
();
}
assertQuery
(
"cust_id\tccy\tbalance\n1\tEUR\t140.6\n"
,
"select * from balances"
,
null
,
true
);
try
{
compiler
.
compile
(
"alter table balances add column newcol int"
,
readOnlyExecutionContext
);
Assert
.
fail
();
}
catch
(
Exception
ex
)
{
Assert
.
assertTrue
(
ex
.
toString
().
contains
(
"permission denied"
));
}
assertQuery
(
"cust_id\tccy\tbalance\n1\tEUR\t140.6\n"
,
"select * from balances"
,
null
,
true
);
});
}
@Test
public
void
testRenameTableDeniedOnNoWriteAccess
()
throws
Exception
{
assertMemoryLeak
(()
->
{
compiler
.
compile
(
"create table balances(cust_id int, ccy symbol, balance double)"
,
sqlExecutionContext
);
try
{
compiler
.
compile
(
"rename table balances to newname"
,
readOnlyExecutionContext
);
Assert
.
fail
();
}
catch
(
Exception
ex
)
{
Assert
.
assertTrue
(
ex
.
toString
().
contains
(
"permission denied"
));
}
assertQuery
(
"count\n0\n"
,
"select count() from balances"
,
null
);
});
}
@Test
public
void
testBackupTableDeniedOnNoWriteAccess
()
throws
Exception
{
assertMemoryLeak
(()
->
{
compiler
.
compile
(
"create table balances(cust_id int, ccy symbol, balance double)"
,
sqlExecutionContext
);
try
{
compiler
.
compile
(
"backup table balances"
,
readOnlyExecutionContext
);
Assert
.
fail
();
}
catch
(
Exception
ex
)
{
Assert
.
assertTrue
(
ex
.
toString
().
contains
(
"permission denied"
));
}
});
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录