Skip to content

Commit

Permalink
Merge REL1_6_STABLE into master
Browse files Browse the repository at this point in the history
  • Loading branch information
jcflack committed Jun 14, 2023
2 parents 882906d + 18147d9 commit dd7a922
Show file tree
Hide file tree
Showing 22 changed files with 1,098 additions and 248 deletions.
228 changes: 185 additions & 43 deletions .github/workflows/ci-runnerpg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
# cc: msvc
# - os: windows-latest
# cc: mingw
java: [9, 11, 12, 13, 14, 15]
java: [9, 11, 12, 17, 18, 19]

steps:

Expand Down Expand Up @@ -59,6 +59,9 @@ jobs:
- name: Obtain PG development files (Ubuntu, PGDG)
if: ${{ 'Linux' == runner.os }}
run: |
curl -s -S https://www.postgresql.org/media/keys/ACCC4CF8.asc |
gpg --dearmor |
sudo dd of=/etc/apt/trusted.gpg.d/apt.postgresql.org.gpg
echo \
deb \
http://apt.postgresql.org/pub/repos/apt \
Expand Down Expand Up @@ -192,30 +195,44 @@ jobs:
-execution local \
"-J--class-path=$packageJar$pathSep$jdbcJar" \
"--class-path=$packageJar" \
"-J--add-modules=java.sql.rowset" \
"-J--add-modules=java.sql.rowset,jdk.httpserver" \
"-J-Dpgconfig=$pgConfig" \
"-J-Dcom.impossibl.shadow.io.netty.noUnsafe=true" \
"-J-DmavenRepo=$mavenRepo" \
"-J-DsaxonVer=$saxonVer" - <<\ENDJSHELL
boolean succeeding = false; // begin pessimistic
import static java.nio.file.Files.createTempFile
import static java.nio.file.Files.write
import java.nio.file.Path
import static java.nio.file.Paths.get
import java.sql.Connection
import java.sql.PreparedStatement
import java.sql.ResultSet
import org.postgresql.pljava.packaging.Node
import static org.postgresql.pljava.packaging.Node.q
import static org.postgresql.pljava.packaging.Node.stateMachine
import static org.postgresql.pljava.packaging.Node.isVoidResultSet
import static org.postgresql.pljava.packaging.Node.s_isWindows
import static java.nio.file.Files.createTempFile;
import static java.nio.file.Files.write;
import java.nio.file.Path;
import static java.nio.file.Paths.get;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.postgresql.pljava.packaging.Node;
import static org.postgresql.pljava.packaging.Node.q;
import static org.postgresql.pljava.packaging.Node.stateMachine;
import static org.postgresql.pljava.packaging.Node.isVoidResultSet;
import static org.postgresql.pljava.packaging.Node.s_isWindows;
/*
* Imports that will be needed to serve a jar file over http
* when the time comes for testing that.
*/
import static java.nio.charset.StandardCharsets.UTF_8;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import com.sun.net.httpserver.BasicAuthenticator;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
String javaHome = System.getProperty("java.home");
Path javaLibDir = get(javaHome, s_isWindows ? "bin" : "lib")
Path javaLibDir = get(javaHome, s_isWindows ? "bin" : "lib");
Path libjvm = (
"Mac OS X".equals(System.getProperty("os.name"))
Expand All @@ -225,12 +242,16 @@ jobs:
: javaLibDir.resolve(s_isWindows ? "jvm.dll" : "server/libjvm.so")
);
String vmopts = "-enableassertions:org.postgresql.pljava... -Xcheck:jni"
String vmopts =
"-enableassertions:org.postgresql.pljava... -Xcheck:jni";
Node n1 = Node.get_new_node("TestNode1")
if ( 17 < Runtime.version().feature() )
vmopts += " -Djava.security.manager=allow";
Node n1 = Node.get_new_node("TestNode1");
if ( s_isWindows )
n1.use_pg_ctl(true)
n1.use_pg_ctl(true);
/*
* Keep a tally of the three types of diagnostic notices that may be
Expand All @@ -241,7 +262,7 @@ jobs:
Map<String,Integer> results =
Stream.of("info", "warning", "error", "ng").collect(
LinkedHashMap<String,Integer>::new,
(m,k) -> m.put(k, 0), (r,s) -> {})
(m,k) -> m.put(k, 0), (r,s) -> {});
boolean isDiagnostic(Object o, Set<String> whatIsNG)
{
Expand All @@ -258,6 +279,42 @@ jobs:
return true;
}
/*
* Write a trial policy into a temporary file in n's data_dir,
* and set pljava.vmoptions accordingly over connection c.
* Returns the 'succeeding' flag from the state machine looking
* at the command results.
*/
boolean useTrialPolicy(Node n, Connection c, List<String> contents)
throws Exception
{
Path trialPolicy =
createTempFile(n.data_dir().getParent(), "trial", "policy");
write(trialPolicy, contents);
PreparedStatement setVmOpts = c.prepareStatement(
"SELECT null::pg_catalog.void" +
" FROM pg_catalog.set_config('pljava.vmoptions', ?, false)"
);
setVmOpts.setString(1, vmopts +
" -Dorg.postgresql.pljava.policy.trial=" + trialPolicy.toUri());
return stateMachine(
"change pljava.vmoptions",
null,
q(setVmOpts, setVmOpts::execute)
.flatMap(Node::semiFlattenDiagnostics)
.peek(Node::peek),
(o,p,q) -> isDiagnostic(o, Set.of("error")) ? 1 : -2,
(o,p,q) -> isVoidResultSet(o, 1, 1) ? 3 : false,
(o,p,q) -> null == o
);
}
try (
AutoCloseable t1 = n1.initialized_cluster();
AutoCloseable t2 = n1.started_server(Map.of(
Expand Down Expand Up @@ -333,61 +390,146 @@ jobs:
*/
try ( Connection c2 = n1.connect() )
{
Path trialPolicy =
createTempFile(n1.data_dir().getParent(), "trial", "policy");
write(trialPolicy, List.of(
succeeding &= useTrialPolicy(n1, c2, List.of(
"grant {",
" permission",
" org.postgresql.pljava.policy.TrialPolicy$Permission;",
"};"
));
PreparedStatement setVmOpts = c2.prepareStatement(
"SELECT null::pg_catalog.void" +
" FROM pg_catalog.set_config('pljava.vmoptions', ?, false)"
PreparedStatement tryForbiddenRead = c2.prepareStatement(
"SELECT" +
" CASE WHEN javatest.java_getsystemproperty('java.home')" +
" OPERATOR(pg_catalog.=) ?" +
" THEN javatest.logmessage('INFO', 'trial policy test ok')" +
" ELSE javatest.logmessage('WARNING', 'trial policy test ng')" +
" END"
);
setVmOpts.setString(1, vmopts +
" -Dorg.postgresql.pljava.policy.trial=" + trialPolicy.toUri());
tryForbiddenRead.setString(1, javaHome);
succeeding &= stateMachine(
"change pljava.vmoptions",
"try to read a forbidden property",
null,
q(setVmOpts, setVmOpts::execute)
q(tryForbiddenRead, tryForbiddenRead::execute)
.flatMap(Node::semiFlattenDiagnostics)
.peek(Node::peek),
(o,p,q) -> isDiagnostic(o, Set.of("error")) ? 1 : -2,
(o,p,q) -> isDiagnostic(o, Set.of("error", "warning")) ? 1 : -2,
(o,p,q) -> isVoidResultSet(o, 1, 1) ? 3 : false,
(o,p,q) -> null == o
);
// done with connection c2
}
PreparedStatement tryForbiddenRead = c2.prepareStatement(
"SELECT" +
" CASE WHEN javatest.java_getsystemproperty('java.home')" +
" OPERATOR(pg_catalog.=) ?" +
" THEN javatest.logmessage('INFO', 'trial policy test ok')" +
" ELSE javatest.logmessage('WARNING', 'trial policy test ng')" +
" END"
/*
* Spin up an http server with a little jar file to serve, and test
* that install_jar works with an http: url.
*
* First make a little jar empty but for a deployment descriptor.
*/
String ddrName = "foo.ddr";
Attributes a = new Attributes();
a.putValue("SQLJDeploymentDescriptor", "TRUE");
Manifest m = new Manifest();
m.getEntries().put(ddrName, a);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
JarOutputStream jos = new JarOutputStream(baos, m);
jos.putNextEntry(new ZipEntry(ddrName));
jos.write(
(
"SQLActions[]={\n\"BEGIN INSTALL\n" +
"SELECT javatest.logmessage('INFO'," +
" 'jar installed from http');\n" +
"END INSTALL\",\n\"BEGIN REMOVE\n" +
"BEGIN dummy\n" +
"END dummy;\n" +
"END REMOVE\"\n}\n"
).getBytes(UTF_8)
);
jos.closeEntry();
jos.close();
byte[] jar = baos.toByteArray();
/*
* Now an http server.
*/
HttpServer hs =
HttpServer.create(new InetSocketAddress("localhost", 0), 0);
try (
Connection c2 = n1.connect();
AutoCloseable t = ((Supplier<AutoCloseable>)() ->
{
hs.start();
return () -> hs.stop(0);
}
).get()
)
{
InetSocketAddress addr = hs.getAddress();
String id = "bar", pw = "baz";
URL u = new URI(
"http", id+':'+pw, addr.getHostString(), addr.getPort(),
"/foo.jar", null, null
).toURL();
HttpContext hc = hs.createContext(
u.getPath(),
new HttpHandler()
{
@Override
public void handle(HttpExchange t) throws IOException
{
try ( InputStream is = t.getRequestBody() ) {
is.readAllBytes();
}
t.getResponseHeaders().add(
"Content-Type", "application/java-archive");
t.sendResponseHeaders(200, jar.length);
try ( OutputStream os = t.getResponseBody() ) {
os.write(jar);
}
}
}
);
tryForbiddenRead.setString(1, javaHome);
hc.setAuthenticator(
new BasicAuthenticator("CI realm")
// ("CI realm", UTF_8) only available in Java 14 or later
{
@Override
public boolean checkCredentials(String c_id, String c_pw)
{
return id.equals(c_id) && pw.equals(c_pw);
}
}
);
succeeding &= useTrialPolicy(n1, c2, List.of(
"grant codebase \"${org.postgresql.pljava.codesource}\" {",
" permission",
" java.net.URLPermission \"http:*\", \"GET:Accept\";",
"};"
));
succeeding &= stateMachine(
"try to read a forbidden property",
"install a jar over http",
null,
q(tryForbiddenRead, tryForbiddenRead::execute)
Node.installJar(c2, u.toString(), "foo", true)
.flatMap(Node::semiFlattenDiagnostics)
.peek(Node::peek),
(o,p,q) -> isDiagnostic(o, Set.of("error", "warning")) ? 1 : -2,
(o,p,q) -> isVoidResultSet(o, 1, 1) ? 3 : false,
(o,p,q) -> null == o
);
// done with connection c2
// done with connection c2 again, and the http server
}
/*
Expand Down Expand Up @@ -556,5 +698,5 @@ jobs:
System.out.println(results);
succeeding &= (0 == results.get("ng"));
System.exit(succeeding ? 0 : 1)
System.exit(succeeding ? 0 : 1);
ENDJSHELL
Loading

0 comments on commit dd7a922

Please sign in to comment.