Skip to content

Conclave Init

Conclave Init is a tool for bootstrapping Conclave projects, reducing the amount of boilerplate you need to write.

You can use the tool once you have set up your machine and installed Conclave. (You can use the community edition for the purposes of this tutorial!)

Conclave Init will automatically generate your Conclave project so that you can focus on writing enclave code!

Generate a new project

You will find conclave-init.jar in the tools directory of the Conclave SDK. To create a new Conclave project, run the following command:

1
2
3
4
java -jar /path/to/conclave-sdk/tools/conclave-init.jar \
  --package com.megacorp \
  --enclave-class-name AmazingEnclave \
  --target ./amazing-conclave-app

Tip

Conclave Init also supports Kotlin. Try appending the command with --language kotlin.

Run java -jar conclave-init.jar --help to see all available options.

  • A new project has been created in the amazing-conclave-app directory, as specified by --target ./amazing-conclave-app.
  • The enclave directory contains the enclave module. The class AmazingEnclave has been added to the package com.megacorp.enclave. The project is ready for you to start implementing your enclave code here!
  • The host directory has been created, too. It contains only a build.gradle file, since that's all that's required for the Conclave web host.
  • The client directory contains a basic client which can interact with the web host.

Next steps

  • If you've done this before, you can now start implementing your enclave in the generated project.
  • If you'd like to learn how to implement a Conclave app using this project as a starting point, head to the Writing your first enclave tutorial.
  • If you'd like to read a description of the files that have been generated, see the appendix.

Run the tests

From the newly created project directory, run the tests with

1
./gradlew test -PenclaveMode=<MODE>

where MODE is the enclave mode.

Run the application

Note

Projects created by Conclave Init are configured to use the Conclave web host and web client. However, you are free to reconfigure the project to use a different host or client.

  1. Build and run the host with

    1
    2
    ./gradlew :host:shadowJar -PenclaveMode=<MODE>
    java -jar host/build/libs/host-<MODE>.jar
    
    where MODE is the enclave mode in lowercase. For example:
    1
    2
    ./gradlew :host:shadowJar -PenclaveMode=mock
    java -jar host/build/libs/host-mock.jar
    
    This will spin up a Spring Boot server. You will know it's ready when you see the following output:
    1
    INFO com.r3.conclave.host.web.EnclaveWebHost$Companion - Started EnclaveWebHost.Companion in <SECONDS> seconds
    

  2. In a separate terminal, build and run the client with

    1
    2
    3
    4
    ./gradlew :client:shadowJar
    
    java -jar client/build/libs/client-all.jar \
        "S:<SIGNING_KEY_HASH> PROD:1 SEC:INSECURE"
    
    If you are using mock mode (the default), the SIGNING_KEY_HASH will be 0000000000000000000000000000000000000000000000000000000000000000. For any mode, you can grab it from the line in the host output which starts with "Code signing key hash". You should see the output
    1
    Enclave returned 321
    
    which has been hardcoded in the enclave's receiveMail() function.

Java Compatibility

By default, Gradle will compile the generated Java project using the current Java version. Conclave needs at least Java 8, but if you want to compile to a different version then you can do so. See the Gradle docs for details on how to do this.

The following code in the root build.gradle of the generated project tells Gradle to compile the project to Java 11 bytecode:

1
2
3
4
5
6
7
8
9
tasks.withType(AbstractCompile) {
    if (it.class.name.startsWith('org.jetbrains.kotlin.gradle.tasks.KotlinCompile')) {
        kotlinOptions {
            jvmTarget = "11"
            apiVersion = '1.5'
            languageVersion = '1.5'
        }
    }
}

If you want to revert to Java 8, remove the block or set jvmTarget=1.8. See the Kotlin docs for more details.

Note

Since this project uses Gradle 6, the KotlinCompile task is not directly available. Hence we use AbstractCompile instead.

Appendix: Description of Generated Files

The majority of the files generated by Conclave Init contain boilerplate code which configures the project's Gradle build. These files are highlighted in the file tree diagram below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
.
├── build.gradle
├── client
│   ├── build.gradle
│   └── src/main/java/com/example/tutorial/client/ReverseEnclaveClient.java
├── enclave
│   ├── build.gradle
│   └── src/main/java/com/example/tutorial/enclave/ReverseEnclave.java
│   └── src/test/java/com/example/tutorial/enclave/ReverseEnclaveTest.java
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── host
│   └── build.gradle
├── README.md
└── settings.gradle

This section will describe the contents of these configuration files that Conclave Init has generated.

In later sections, we will be modifying the generated Java source files to implement the sample application.

Root directory

The files in this directory configure the gradle wrapper. See the Gradle docs for more details.

Command-line tool for interacting with Gradle on macOS and Linux.

Command-line tool for interacting with Gradle on Windows.

This file contains the following configuration:

  • It imports the Conclave SDK repo, using the conclaveRepo Gradle property. See Gradle properties for more information.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    pluginManagement {
        repositories {
            maven {
                def repoPath = file(rootDir.relativePath(file(conclaveRepo)))
                // ...
                url = repoPath
            }
            // Add standard repositories back.
            gradlePluginPortal()
            jcenter()
            mavenCentral()
        }
    
  • It applies the Conclave Gradle plugin using the conclaveVersion Gradle property.
    1
    2
    3
    4
        plugins {
            id 'com.r3.conclave.enclave' version conclaveVersion apply false
        }
    }
    
  • It includes the enclave, host, and client subprojects in the Gradle multi-project build.
    1
    2
    3
    include 'enclave'
    include 'host'
    include 'client'
    

This is the top-level build.gradle file which provides common config that applies to the entire project.

  • It applies and configures plugins.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    plugins {
        id 'java'
        id 'idea'
        id 'org.jetbrains.kotlin.jvm' version '1.5.31' apply false
    }
    
    allprojects {
      idea {
        module {
          downloadJavadoc = true
        }
      }
    }
    
    subprojects {
        apply plugin: 'idea'
        apply plugin: "org.jetbrains.kotlin.jvm"
    
        ...
    

Tip

See Ide Configuration for more information on the idea plugin.

  • It imports the Conclave SDK repository into our project using the conclaveRepo Gradle property. See Gradle Properties for more information on this.
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
        ...
    
        repositories {
            maven {
                url = rootProject.file(conclaveRepo)
            }
            mavenCentral()
        }
    
        ...
    
  • It enables the test runner and configures the test log output.
    1
    2
    3
    4
    5
    6
    7
    8
    9
        ...
    
        tasks.withType(Test) {
            useJUnitPlatform()
            testLogging {
                events "passed", "skipped", "failed"
            }
        }
    }
    

Defines some versions of dependencies. Note, we assume that the required conclaveRepo and conclaveVersion properties are set in the user-wide gradle.properties file.

Enclave, host, and client modules

The enclave, host, and client are the three components in a Conclave application. See Conclave Architecture for more information.

You may have noticed that there are no Java source files in the host/ directory. There's no need to write any host code if using the bundled web server! The host module uses the Conclave web host implementation, so we don't have to implement our own host. All we need is the host/build.gradle file, which applies the following configuration to the host module:

  • Applies plugins:

    • The Gradle Application plugin allows us run the host web server from the command line.
    • The Spring boot plugin allows us to run the host application from a single "fat" JAR containing all the dependencies.
      1
      2
      3
      4
      plugins {
          id 'application'
          id 'org.springframework.boot' version '2.0.1.RELEASE'
      }
      
  • Configures the Application plugin. This sets the host's main class as the Conclave web host, which is provided in the SDK.

    1
    2
    3
    application {
        mainClassName = "com.r3.conclave.host.web.EnclaveWebHost"
    }
    

  • Defines the -PenclaveMode command-line parameter that lets us select the mode in which to build and run the host. See Running your first enclave and Enclave Modes for more information.

    1
    def mode = findProperty("enclaveMode")?.toString()?.toLowerCase() ?: "mock"
    

  • Creates a task that can be used for generating signing materials. This is optional, but we use it to create a more secure signature in release mode. See Signing for more information.

    1
    2
    3
    tasks.register("prepareForSigning") {
        it.dependsOn(":enclave:generateEnclaveSigningMaterial${mode.capitalize()}")
    }
    

  • Adds required dependencies on the enclave module and the Conclave web host library. Since we aren't going to implement any code in this module, the dependencies are runtimeOnly.

    1
    2
    3
    4
    dependencies {
        runtimeOnly project(path: ":enclave", configuration: mode)
        runtimeOnly "com.r3.conclave:conclave-web-host:$conclaveVersion"
    }
    

  • Configures the filename of the host JAR to be "host-MODE.jar" where MODE is the enclave mode.

    1
    2
    3
    bootJar {
        archiveClassifier.set(mode)
    }
    

The enclave build.gradle file does the following:

  • Applies the Conclave plugin.

    1
    2
    3
    plugins {
        id 'com.r3.conclave.enclave'
    }
    

  • Adds a dependency on the JUnit Jupiter testing package. Notice how the Conclave libraries are not included here. The Conclave plugin handles those dependencies for us.

    1
    2
    3
    dependencies {
        testImplementation "org.junit.jupiter:junit-jupiter:$jupiterVersion"
    }
    

  • Configures the Conclave plugin. (See Conclave configuration options for more information.)

    • The productID is used to distinguish enclaves produced by the same organisation.
    • The revocationLevel should be incremented when a weakness or vulnerability in the enclave code is discovered and fixed.
      1
      2
      3
      4
      conclave {
          productID = 1
          revocationLevel = 0
      }
      

Tip

Since we haven't specified a signing configuration, we will use the default signing configuration for our enclave. You may want to customise the signing configuration. See Signing for more information.

The client is a simple Java application. The client/build.gradle file does the following:

  • Applies and configures plugins:

    • The Gradle Application plugin allows us run the application from the command line. This time, the mainClassName is set to our own client class, since we will be implementing the client ourselves. This is in comparison to host/build.gradle, where the main class is provided by the Conclave SDK.
    • The Shadow plugin allows us to run the client application from a single "fat" JAR containing all the dependencies.
      1
      2
      3
      4
      5
      6
      7
      8
      plugins {
          id 'application'
          id 'com.github.johnrengelman.shadow' version '6.1.0'
      }
      
      application {
          mainClassName = "com.example.tutorial.client.ReverseEnclaveClient"
      }
      
  • Configures dependencies.

    • We will use the conclave-web-client library to interact with the Conclave web host.
      1
      2
      3
      4
      5
      dependencies {
          implementation "com.r3.conclave:conclave-web-client:$conclaveVersion"
      
          runtimeOnly "org.slf4j:slf4j-simple:$slf4jVersion"
      }