oracle / graalpython

A high-performance embeddable Python 3 runtime for Java
https://www.graalvm.org/python/
Other
1.22k stars 104 forks source link

Bouncy Castle FIPS support #407

Closed 343996019 closed 2 months ago

343996019 commented 3 months ago

Hello,

We are going to use the python-community in our program, the python-community depends on the Bouncy Castle, but our program is using Bouncy Castle FIPS, it's not compatible to put both Bouncy Castle FIPS and Bouncy Castle non-FIPS jars in the classpath, my question is Can the python-community work with Bouncy Castle FIPS, if yes, how? if not, is there any plan about the support of Bouncy Castle FIPS? Thank you!

msimacek commented 3 months ago

I couldn't find any documentation on what's the actual difference in contents between those two. We only use very few classes from bouncycastle, mostly for certificate handling, so I think it's likely it would work if you just replace the dependency. But given that it's only used for the ssl module, if you don't need to use the ssl module from python, you should be able to just remove the dependency (you can also set the system property python.WithoutSSL to disable the ssl module altogether). I'm not aware of any plans to officially support boucycastle FIPS.

343996019 commented 3 months ago

@msimacek Thanks for your suggestions, I tried to exclude the Bouncy Castle from the dependencies and set the system property python.WithoutSSL as true as below.

package org.leix;

import java.nio.file.Path; import java.util.; import java.io.;

import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Value; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.PolyglotAccess; import org.graalvm.polyglot.io.IOAccess;

public class HelloPolyglot { public static void main(String[] args) { try {

        Map<String, String> options = new HashMap<>();
        options.put("python.EmulateJython", "true");
        options.put("engine.WarnInterpreterOnly", "false");

        System.setProperty("python.WithoutSSL", "true");

        File workingFile = new File("D:\\workspace\\graalpython\\src\\main\\java\\org\\leix\\workspace");
        Path workingDirectory = workingFile.toPath();
        options.put("python.PythonPath", workingDirectory.toString());
        Context context = Context.newBuilder("python").options(options)
                .allowExperimentalOptions(true)
                .allowAllAccess(true)

                .allowPolyglotAccess(PolyglotAccess.AL)
                .allowIO(IOAccess.ALL)
                .build();

        String name = "test.py";
        File file = new File(workingDirectory.toString(), name);
        Source sAccess(PolyglotAccess.AL)
                .allowIO(IOAccess.ALL)
                .build();
        //String dir = "D:\\workspace\\graalpython\\src\\main\\java\\org\\leix";ource = Source.newBuilder("python", file).build();
        context.eval(source);
        Value test = context.getBindings("python").getMember("test");
        System.out.println(test.execute("framework").asString());

    }
    catch(IOException e) {
        e.printStackTrace();
    }
}

}

but I'm still facing the same issue as below

Exception in thread "main" java.lang.InternalError: The polyglot class isolation failed to load and resolve the module layer. This is typically caused by invalid class-path-entries or duplicated packages on the class-path. Use -Dpolyglotimpl.TraceClassPathIsolation=true to print more details about class loading isolation. If the problem persists, it is recommended to use the module-path instead of the class-path to load polyglot. at org.graalvm.polyglot.Engine$ClassPathIsolation.createIsolatedTruffleModule(Engine.java:1812) at org.graalvm.polyglot.Engine$ClassPathIsolation.createIsolatedTruffle(Engine.java:1723) at org.graalvm.polyglot.Engine$1.searchServiceLoader(Engine.java:1682) at org.graalvm.polyglot.Engine$1.run(Engine.java:1668) at org.graalvm.polyglot.Engine$1.run(Engine.java:1663) at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) at org.graalvm.polyglot.Engine.initEngineImpl(Engine.java:1663) at org.graalvm.polyglot.Engine$ImplHolder.(Engine.java:186) at org.graalvm.polyglot.Engine.getImpl(Engine.java:438) at org.graalvm.polyglot.Engine$Builder.build(Engine.java:736) at org.graalvm.polyglot.Context$Builder.build(Context.java:1925) at org.leix.HelloPolyglot.main(HelloPolyglot.java:34) Caused by: java.lang.module.FindException: Module org.bouncycastle.util not found, required by org.graalvm.py at java.base/java.lang.module.Resolver.findFail(Resolver.java:893) at java.base/java.lang.module.Resolver.resolve(Resolver.java:192) at java.base/java.lang.module.Resolver.bind(Resolver.java:315) at java.base/java.lang.module.Resolver.bind(Resolver.java:219) at java.base/java.lang.module.Configuration.resolveAndBind(Configuration.java:492) at java.base/java.lang.module.Configuration.resolveAndBind(Configuration.java:298) at org.graalvm.polyglot.Engine$ClassPathIsolation.createIsolatedTruffleModule(Engine.java:1810) ... 11 more

Do we need to build the graalpython with option -Dpython.WithoutSSL=true?

msimacek commented 2 months ago

Just rebuilding it won't help, it's because of the Java module dependencies, you'd have to modify the source. But you can bypass the module checks if you use classpath instead of module path (which is a hack, not sure if there's a way to ignore a dependency when using module path). And I found that also the hashlib module uses bouncycastle. It can be disabled with python.WithoutDigest property. I could get an application embedding graalpy to start with bouncycastle excluded using this pom and running it with mvn package exec:exec (replace the main class name in the exec plugin configuration):

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>graalpy-example</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <graalvm.version>24.0.0</graalvm.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.graalvm.polyglot</groupId>
            <artifactId>polyglot</artifactId>
            <version>${graalvm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.graalvm.polyglot</groupId>
            <artifactId>python</artifactId>
            <version>${graalvm.version}</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.bouncycastle</groupId>
                    <artifactId>bcutil-jdk18on</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bouncycastle</groupId>
                    <artifactId>bcpkix-jdk18on</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bouncycastle</groupId>
                    <artifactId>bcprov-jdk18on</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>21</source>
                    <target>21</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.1.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <executable>${java.home}/bin/java</executable>
                    <arguments>
                        <argument>-cp</argument>
                        <classpath/>
                        <argument>-Dpython.WithoutSSL=true</argument>
                        <argument>-Dpython.WithoutDigest=true</argument>
                        <argument>com.example.Main</argument>
                    </arguments>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
343996019 commented 2 months ago

@msimacek Thank you! it works for me as well.

msimacek commented 2 months ago

I'm glad it helped. I'll close this issue then.