pgsqlarbiter 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/pgsqlarbiter/analysis.rb +14 -0
- data/lib/pgsqlarbiter/analyzer.rb +504 -0
- data/lib/pgsqlarbiter/arbiter.rb +84 -0
- data/lib/pgsqlarbiter/default_query_functions.rb +177 -0
- data/lib/pgsqlarbiter/error.rb +18 -0
- data/lib/pgsqlarbiter/keywords.rb +66 -0
- data/lib/pgsqlarbiter/lexer.rb +272 -0
- data/lib/pgsqlarbiter/token.rb +34 -0
- data/lib/pgsqlarbiter/verdict.rb +37 -0
- data/lib/pgsqlarbiter/version.rb +5 -0
- data/lib/pgsqlarbiter.rb +70 -0
- metadata +80 -0
data/lib/pgsqlarbiter.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "pgsqlarbiter/version"
|
|
4
|
+
require_relative "pgsqlarbiter/error"
|
|
5
|
+
require_relative "pgsqlarbiter/token"
|
|
6
|
+
require_relative "pgsqlarbiter/keywords"
|
|
7
|
+
require_relative "pgsqlarbiter/analysis"
|
|
8
|
+
require_relative "pgsqlarbiter/default_query_functions"
|
|
9
|
+
require_relative "pgsqlarbiter/lexer"
|
|
10
|
+
require_relative "pgsqlarbiter/analyzer"
|
|
11
|
+
require_relative "pgsqlarbiter/verdict"
|
|
12
|
+
require_relative "pgsqlarbiter/arbiter"
|
|
13
|
+
|
|
14
|
+
# SQL query permission system for PostgreSQL.
|
|
15
|
+
#
|
|
16
|
+
# Pgsqlarbiter restricts database access for semi-trusted users by ensuring only
|
|
17
|
+
# single-statement DML queries are executed and all referenced tables, views, and
|
|
18
|
+
# functions are whitelisted.
|
|
19
|
+
module Pgsqlarbiter
|
|
20
|
+
# Analyze a SQL query and extract its statement type, referenced tables, and function calls.
|
|
21
|
+
#
|
|
22
|
+
# @param sql [String] the SQL query to analyze
|
|
23
|
+
# @return [Analysis] analysis result containing statement_type, tables, and functions
|
|
24
|
+
# @raise [ParseError] if the SQL cannot be parsed
|
|
25
|
+
# @raise [MultipleStatementsError] if the SQL contains more than one statement
|
|
26
|
+
# @raise [DisallowedStatementError] if the statement type is not a supported DML type
|
|
27
|
+
def self.analyze(sql)
|
|
28
|
+
Analyzer.new.analyze(sql)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Judge a SQL query against the given restrictions, returning a {Verdict} that
|
|
32
|
+
# explains which checks passed or failed.
|
|
33
|
+
#
|
|
34
|
+
# This is a convenience method that creates a one-off {Arbiter} instance. For repeated
|
|
35
|
+
# checks with the same rules, prefer creating an {Arbiter} directly.
|
|
36
|
+
#
|
|
37
|
+
# @param sql [String] the SQL query to judge
|
|
38
|
+
# @param allowed_tables [Array<String>] allowed table and view names
|
|
39
|
+
# @param allowed_statement_types [Array<Symbol>] allowed statement types
|
|
40
|
+
# (default: +[:select]+). Valid types: +:select+, +:insert+, +:update+,
|
|
41
|
+
# +:delete+, +:merge+, +:values+
|
|
42
|
+
# @param allowed_functions [Set<String>, Array<String>] allowed function names
|
|
43
|
+
# (default: {DEFAULT_QUERY_FUNCTIONS})
|
|
44
|
+
# @return [Verdict] detailed result with {Verdict#allowed?}, individual check
|
|
45
|
+
# results, and {Verdict#reasons}
|
|
46
|
+
# @raise [MultipleStatementsError] if the SQL contains more than one statement
|
|
47
|
+
# @raise [DisallowedStatementError] if the statement type is not a supported DML type
|
|
48
|
+
def self.judge(sql, allowed_tables:, allowed_statement_types: [:select], allowed_functions: DEFAULT_QUERY_FUNCTIONS)
|
|
49
|
+
Arbiter.new(allowed_statement_types: allowed_statement_types, allowed_tables: allowed_tables, allowed_functions: allowed_functions).judge(sql)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Check whether a SQL query is allowed under the given restrictions.
|
|
53
|
+
#
|
|
54
|
+
# This is a convenience method that creates a one-off {Arbiter} instance. For repeated
|
|
55
|
+
# checks with the same rules, prefer creating an {Arbiter} directly.
|
|
56
|
+
#
|
|
57
|
+
# @param sql [String] the SQL query to check
|
|
58
|
+
# @param allowed_tables [Array<String>] allowed table and view names
|
|
59
|
+
# @param allowed_statement_types [Array<Symbol>] allowed statement types
|
|
60
|
+
# (default: +[:select]+). Valid types: +:select+, +:insert+, +:update+,
|
|
61
|
+
# +:delete+, +:merge+, +:values+
|
|
62
|
+
# @param allowed_functions [Set<String>, Array<String>] allowed function names
|
|
63
|
+
# (default: {DEFAULT_QUERY_FUNCTIONS})
|
|
64
|
+
# @return [Boolean] +true+ if the query is allowed, +false+ otherwise
|
|
65
|
+
# @raise [MultipleStatementsError] if the SQL contains more than one statement
|
|
66
|
+
# @raise [DisallowedStatementError] if the statement type is not a supported DML type
|
|
67
|
+
def self.allow?(sql, allowed_tables:, allowed_statement_types: [:select], allowed_functions: DEFAULT_QUERY_FUNCTIONS)
|
|
68
|
+
Arbiter.new(allowed_statement_types: allowed_statement_types, allowed_tables: allowed_tables, allowed_functions: allowed_functions).allow?(sql)
|
|
69
|
+
end
|
|
70
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: pgsqlarbiter
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- pgsqlarbiter contributors
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: minitest
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '5.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '5.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rake
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '13.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '13.0'
|
|
40
|
+
description: Restricts SQL queries to single-statement DML with whitelisted tables,
|
|
41
|
+
views, and functions.
|
|
42
|
+
executables: []
|
|
43
|
+
extensions: []
|
|
44
|
+
extra_rdoc_files: []
|
|
45
|
+
files:
|
|
46
|
+
- lib/pgsqlarbiter.rb
|
|
47
|
+
- lib/pgsqlarbiter/analysis.rb
|
|
48
|
+
- lib/pgsqlarbiter/analyzer.rb
|
|
49
|
+
- lib/pgsqlarbiter/arbiter.rb
|
|
50
|
+
- lib/pgsqlarbiter/default_query_functions.rb
|
|
51
|
+
- lib/pgsqlarbiter/error.rb
|
|
52
|
+
- lib/pgsqlarbiter/keywords.rb
|
|
53
|
+
- lib/pgsqlarbiter/lexer.rb
|
|
54
|
+
- lib/pgsqlarbiter/token.rb
|
|
55
|
+
- lib/pgsqlarbiter/verdict.rb
|
|
56
|
+
- lib/pgsqlarbiter/version.rb
|
|
57
|
+
homepage: https://github.com/pgsqlarbiter/pgsqlarbiter-rb
|
|
58
|
+
licenses:
|
|
59
|
+
- MIT
|
|
60
|
+
metadata:
|
|
61
|
+
homepage_uri: https://github.com/pgsqlarbiter/pgsqlarbiter-rb
|
|
62
|
+
source_code_uri: https://github.com/pgsqlarbiter/pgsqlarbiter-rb
|
|
63
|
+
rdoc_options: []
|
|
64
|
+
require_paths:
|
|
65
|
+
- lib
|
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '3.4'
|
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
requirements: []
|
|
77
|
+
rubygems_version: 4.0.6
|
|
78
|
+
specification_version: 4
|
|
79
|
+
summary: SQL query permission system for PostgreSQL
|
|
80
|
+
test_files: []
|