diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..4d942d5ff --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,23 @@ +name: build +on: [push] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Cache gradle modules + uses: actions/cache@v1 + env: + cache-name: cache-gradle-modules + with: + path: ~/.gradle + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/gradle.build') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: Build + run: | + mkdir -p ~/.gradle + mkdir -p ~/.m2 + ./build.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 34dcad8c4..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,62 +0,0 @@ -# make sure to use a Debian-based image, because otherwise you will run into issue with protoc because of missing glibc on alpine -image: docker - -stages: - - build - - push - -build: - stage: build - image: - name: fraunhoferaisec/docker-build:develop - entrypoint: [""] - before_script: - # defined here because of https://gitlab.com/gitlab-org/gitlab-runner/issues/1809 - - export PROJECT_DIR="${CI_PROJECT_DIR}" - # caching for gradle - - export GRADLE_DIR="${CI_PROJECT_DIR}/cache/.gradle" - - mkdir -p "$GRADLE_DIR" - # caching for mvn (used for karaf-assembly) - - export M2_DIR="${CI_PROJECT_DIR}/cache/.m2" - - mkdir -p "$M2_DIR" - script: - # yarnBuild is part of build, but we try to speed up the process a bit by prioritizing that long-running task - - /run.sh yarnBuild build check dumpVersion --parallel - artifacts: - when: always - paths: - - "*/build/reports" - - "karaf-assembly/build/assembly" - - "rat-repository/build/libs" - - "version.txt" - cache: - key: tc-build - paths: - - "cache" - - "ids-webconsole/src/main/resources/www/node_modules" - -push: - image: jonoh/docker-buildx-qemu - stage: push - dependencies: - - build - before_script: - # Use docker-container driver to allow useful features (push/multi-platform) - - docker buildx create --driver docker-container --use --name tc_builder - - docker buildx inspect --bootstrap - - export TAG_NAME=$(if [ "${CI_COMMIT_REF_NAME}" = "master" ]; then echo "latest"; else echo "${CI_COMMIT_REF_NAME}"; fi) - # Remove the prefixing "v" of version tags for docker registry - - if [[ "$TAG_NAME" =~ v[0-9]+\.[0-9]+\.[0-9]+ ]]; then export TAG_NAME=${TAG_NAME:1}; fi - script: - - echo "$DOCKER_PASS" | docker login --username "$DOCKER_USER" --password-stdin - # Execute buildx script - - chmod +x ./buildx/docker-buildx.sh - - echo "Using image tag ${TAG_NAME}" - - ./buildx/docker-buildx.sh -t ${TAG_NAME} -f docker-compose.yml -f docker-bake-multi.hcl - after_script: - # Remove the buildx builder - - docker buildx rm tc_builder - only: - - develop - - master - - /^v[0-9]+\.[0-9]+\.[0-9]+$/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 50f786039..000000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: java -jdk: - - oraclejdk11 -services: - - docker -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ -cache: - directories: - - $HOME/.m2 - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ -before_install: - - wget -O protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v3.11.4/protoc-3.11.4-linux-x86_64.zip - - mkdir $HOME/protoc && unzip -d $HOME/protoc protoc.zip - - export PATH=$HOME/protoc/bin:$PATH - - echo $PATH - - nvm install 12 - - npm install -g yarn -install: true -script: ./gradlew --parallel clean build diff --git a/README.md b/README.md index cb1e6d0bf..f0000ff66 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.com/industrial-data-space/trusted-connector.svg?branch=develop)](https://travis-ci.org/industrial-data-space/trusted-connector) +![build](https://github.com/industrial-data-space/trusted-connector/workflows/build/badge.svg) The _Trusted Connector_ is an Apache Karaf-based platform for the Industrial Internet of Things (IIoT). It supports Docker and trust|me as containerization environments and provides the following features: diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 46d62a066..000000000 --- a/build.gradle +++ /dev/null @@ -1,263 +0,0 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.yaml.snakeyaml.Yaml - -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath("org.yaml:snakeyaml:1.26") - } -} - -plugins { - id 'java' - id 'com.google.protobuf' version '0.8.10' - id 'com.moowork.node' version '1.3.1' - id 'biz.aQute.bnd' version '4.2.0' apply false - id 'com.github.lburgazzoli.karaf' version '0.5.1' - id 'org.jetbrains.kotlin.jvm' version '1.3.71' - id 'com.github.jlouns.cpe' version '0.5.0' - id 'com.benjaminsproule.swagger' version '1.0.6' - id 'com.diffplug.gradle.spotless' version '3.13.0' - id 'com.github.jk1.dependency-license-report' version '1.2' -} - -licenseReport { - configurations = ['compile', 'providedByFeature', 'providedByBundle'] -} - -allprojects { - group = 'de.fhg.aisec.ids' - version = '3.0.2' - - ext.libraryVersions = new Yaml().loadAs(new FileInputStream(file("${rootDir}/libraryVersions.yaml")), Map.class) - - configurations { - // just to make bills of materials (bom) easier to see in the dependency tree - bom - - // Configuration for dependencies that will be provided through features in the OSGi environment - providedByFeature - - // Configurations for dependencies that will be provided through bundles in the OSGi environment - // Separate configurations are required when two bundles depend on different versions of the same bundle! - providedByBundle - unixSocketBundle - infomodelBundle - - // Configurations for bundles grouped to dedicated features apart from the main ids feature - influxFeature - zmqFeature - - // OSGi core dependencies which will just be there during runtime - osgiCore - - // For artifacts that should be included as "compile" dependencies into published maven artifacts - publishCompile - - // The "compile" configuration needs to be extended for dependency resolution of maven-publish - compile.extendsFrom providedByFeature, providedByBundle, unixSocketBundle, infomodelBundle, osgiCore, publishCompile - // Some compileOnly dependencies are also needed for unit tests - testImplementation.extendsFrom compileOnly - } - - repositories { - mavenCentral() - jcenter() - // References IAIS repository that contains the infomodel artifacts - maven { - url 'https://maven.iais.fraunhofer.de/artifactory/eis-ids-public/' - } - } -} - -subprojects { - apply plugin: 'biz.aQute.bnd.builder' - apply plugin: 'java' - apply plugin: 'maven' - apply plugin: 'kotlin' - - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - - test { - exclude '**/*IT.*' - } - - task integrationTest(type: Test) { - include '**/*IT.*' - systemProperty "project.version", "$project.version" - } - - tasks.withType(Test) { - testLogging { - events "failed" - exceptionFormat "full" - } - } - - check.dependsOn integrationTest - - // define some Bill of Materials (BOM) for all subprojects - dependencies { - // BOM from Karaf, sets common version for OSGi libraries - bom group: 'org.apache.karaf', name: 'karaf', version: libraryVersions.karaf - - // BOM for pax, for jetty, etc. - bom group: 'org.ops4j.pax', name: 'web', version: libraryVersions.pax - - // Needed for kotlin modules, provided at runtime via kotlin-osgi-bundle in karaf-features-ids - compileOnly group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: libraryVersions.kotlin - - // Required for successful build with JDK 11 - compileOnly group: "javax.xml.bind", name: "jaxb-api", version: libraryVersions.jaxb - testImplementation group: "javax.xml.bind", name: "jaxb-api", version: libraryVersions.jaxb - testImplementation group: "com.sun.xml.bind", name: "jaxb-core", version: libraryVersions.jaxb - testImplementation group: "com.sun.xml.bind", name: "jaxb-impl", version: libraryVersions.jaxb - testImplementation group: 'com.sun.activation', name: 'javax.activation', version: libraryVersions.jaxActivation - - testImplementation "org.ops4j.pax.exam:pax-exam-container-karaf:${libraryVersions.paxExam}" - testImplementation "org.ops4j.pax.exam:pax-exam-junit4:${libraryVersions.paxExam}" - testImplementation "org.ops4j.pax.exam:pax-exam:${libraryVersions.paxExam}" - testImplementation "org.ops4j.pax.url:pax-url-aether:2.4.3" - testImplementation "javax.inject:javax.inject:1" - testImplementation "org.slf4j:slf4j-simple:1.7.12" - } - - tasks.withType(KotlinCompile) { - kotlinOptions { - jvmTarget = "1.8" - } - } - - tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' -// options.compilerArgs << '-Xlint:unchecked' -// options.deprecation = true - } - - tasks.withType(Jar) { - jar { - manifest { - // set the vendor - attributes 'Bundle-Vendor': 'Fraunhofer AISEC' - - // TODO: this was set in most of the bnd files. do we really need this? - attributes '-noee': true - } - } - } -} - -configure(subprojects.findAll { it.name != 'examples' }) { - apply plugin: 'com.diffplug.gradle.spotless' - - spotless { - java { - enforceCheck = false // do not really check for now, we first need to format all the files - - googleJavaFormat() - - licenseHeader('''/*- - * ========================LICENSE_START================================= - * ''' + project.name + ''' - * %% - * Copyright (C) $YEAR Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */''').yearSeparator(' - ') - } - } -} - -configure(subprojects.findAll { it.name == 'ids-api' || it.name == 'ids-comm' }) { - apply plugin: 'maven-publish' - apply plugin: 'signing' - - task sourcesJar(type: Jar) { - from sourceSets.main.allSource - from ('src/main') { - include 'proto/**' - } - archiveClassifier = 'sources' - } - - task javadocJar(type: Jar) { - from javadoc - archiveClassifier = 'javadoc' - } - - // Must disable gradle metadata because of infomodel SNAPSHOT dependencies - tasks.withType(GenerateModuleMetadata) { - enabled = false - } - - publishing { - publications { - idsLibrary(MavenPublication) { - from components.java - artifact sourcesJar - artifact javadocJar - pom { - name = 'IDSCP Protocol Library' - description = 'Contains the WebSocket-based Industrial Data Space Communication Protocol (IDSCP)' - url = 'https://github.com/industrial-data-space/trusted-connector' - licenses { - license { - name = 'The Apache License, Version 2.0' - url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' - } - } - developers { - developer { - name = 'Michael Lux' - email = 'michael.lux@aisec.fraunhofer.de' - organization = 'Fraunhofer AISEC' - organizationUrl = 'aisec.fraunhofer.de' - } - } - scm { - connection = 'scm:git:git://github.com:industrial-data-space/trusted-connector.git' - developerConnection = 'scm:git:ssh://github.com:industrial-data-space/trusted-connector.git' - url = 'https://github.com/industrial-data-space/trusted-connector' - } - } - } - } - - repositories { - maven { - def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2" - def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots" - url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl - - credentials { - username = project.findProperty('deployUsername') - password = project.findProperty('deployPassword') - } - } - } - } - - signing { - useGpgCmd() - sign publishing.publications.idsLibrary - } -} - -// Always write project version to version.txt after build/install -task dumpVersion { - new File(project.projectDir, "version.txt").text = project.version -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..901c34f3c --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,179 @@ +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.yaml.snakeyaml.Yaml + +buildscript { + dependencies { + classpath("org.yaml:snakeyaml:1.26") + } +} + +repositories { + mavenCentral() +} + +plugins { + java + maven + id("com.google.protobuf") version "0.8.15" + // WARNING: Versions 5.2.x onwards export java.* packages, which is not allowed in Felix OSGi Resolver! + // See http://karaf.922171.n3.nabble.com/Manifest-import-problems-td4059042.html + id("biz.aQute.bnd") version "5.1.2" apply false + id("org.jetbrains.kotlin.jvm") version "1.4.31" + id("com.github.jlouns.cpe") version "0.5.0" + id("com.diffplug.spotless") version "5.11.0" + id("com.github.jk1.dependency-license-report") version "1.16" +} + +@Suppress("UNCHECKED_CAST") +val libraryVersions: Map = + Yaml().loadAs(file("${rootDir}/libraryVersions.yaml").inputStream(), Map::class.java) as Map +extra.set("libraryVersions", libraryVersions) + +licenseReport { + configurations = arrayOf("compile", "providedByFeature", "providedByBundle") +} + +allprojects { + group = "de.fhg.aisec.ids" + version = "4.0.0" +} + +tasks.build { + subprojects.filter { it.name == "karaf-assembly" }.forEach { + dependsOn(it.tasks.build) + } +} + +subprojects { + repositories { + mavenCentral() +// mavenLocal() + + // References IAIS repository that contains the infomodel artifacts + maven("https://maven.iais.fraunhofer.de/artifactory/eis-ids-public/") + } + + apply(plugin = "biz.aQute.bnd.builder") + apply(plugin = "java") + apply(plugin = "maven") + apply(plugin = "kotlin") + + java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + tasks.test { + exclude("**/*IT.*") + } + + val integrationTest = tasks.register("integrationTest") { + include("**/*IT.*") + systemProperty("project.version", "$project.version") + } + + tasks.check { + dependsOn(integrationTest) + } + + tasks.withType { + testLogging { + events("failed") + exceptionFormat = TestExceptionFormat.FULL + } + } + + // Configuration for dependencies that will be provided through features in the OSGi environment + val providedByFeature by configurations.creating + + // Configurations for dependencies that will be provided through bundles in the OSGi environment + // Separate configurations are required when two bundles depend on different versions of the same bundle! + val providedByBundle by configurations.creating + val unixSocketBundle by configurations.creating + val infomodelBundle by configurations.creating + + // Configurations for bundles grouped to dedicated features apart from the main ids feature + @Suppress("UNUSED_VARIABLE") + val influxFeature by configurations.creating + @Suppress("UNUSED_VARIABLE") + val zmqFeature by configurations.creating + + // OSGi core dependencies which will just be there during runtime + val osgiCore by configurations.creating + + // For artifacts that should be included as "compile" dependencies into published maven artifacts + val publishCompile by configurations.creating + + configurations["compile"].extendsFrom(providedByFeature, providedByBundle, unixSocketBundle, infomodelBundle, + osgiCore, publishCompile) + + dependencies { + // Logging API + providedByBundle("org.slf4j", "slf4j-simple", libraryVersions["slf4j"]) + + // Needed for kotlin modules, provided at runtime via kotlin-osgi-bundle in karaf-features-ids + compileOnly("org.jetbrains.kotlin", "kotlin-stdlib-jdk8", libraryVersions["kotlin"]) + } + + tasks.withType { + kotlinOptions { + jvmTarget = "11" + } + } + + tasks.withType { + options.encoding = "UTF-8" + options.compilerArgs.add("-Xlint:unchecked") +// options.isDeprecation = true + } + + tasks.jar { + manifest { + attributes( + "Bundle-Vendor" to "Fraunhofer AISEC", + "-noee" to true + ) + } + } +} + +configure(subprojects.filter { it.name != "examples" }) { + apply(plugin = "com.diffplug.spotless") + + spotless { + isEnforceCheck = false + + kotlin { + ktfmt().kotlinlangStyle() + licenseHeader("""/*- + * ========================LICENSE_START================================= + * ${project.name} + * %% + * Copyright (C) ${"$"}YEAR Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */""").yearSeparator(" - ") + } + } +} + +// Always write project version to version.txt after build/install +tasks.build { + doLast { + file(project.projectDir).resolve("version.txt").bufferedWriter().use { + it.write(project.version.toString()) + } + } +} \ No newline at end of file diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 diff --git a/buildx/docker-bake-multi.hcl b/buildx/docker-bake-multi.hcl index 243c78285..96468d507 100644 --- a/buildx/docker-bake-multi.hcl +++ b/buildx/docker-bake-multi.hcl @@ -1,46 +1,20 @@ -# Caching not practical here, since build from base image is trivial -target "jdk-base" { - output = ["type=registry"] - platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7"] -} - target "build-container" { output = ["type=registry"] - cache-to = ["registry.netsec.aisec.fraunhofer.de/tc-build-container:cache"] - cache-from = ["registry.netsec.aisec.fraunhofer.de/tc-build-container:cache"] +// cache-to = ["registry.netsec.aisec.fraunhofer.de/tc-build-container:cache"] +// cache-from = ["registry.netsec.aisec.fraunhofer.de/tc-build-container:cache"] platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7"] } target "core" { output = ["type=registry"] - cache-to = ["registry.netsec.aisec.fraunhofer.de/tc-core:cache"] - cache-from = ["registry.netsec.aisec.fraunhofer.de/tc-core:cache"] - platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7"] -} - -target "tpmsim" { - output = ["type=registry"] - cache-to = ["registry.netsec.aisec.fraunhofer.de/tc-tpmsim:cache"] - cache-from = ["registry.netsec.aisec.fraunhofer.de/tc-tpmsim:cache"] +// cache-to = ["registry.netsec.aisec.fraunhofer.de/tc-core:cache"] +// cache-from = ["registry.netsec.aisec.fraunhofer.de/tc-core:cache"] platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7"] } -# Caching not practical here, since build from jdk-base is trivial -target "ttpsim" { - output = ["type=registry"] - platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7"] -} - -target "example-idscp-consumer-app" { - output = ["type=registry"] - cache-to = ["registry.netsec.aisec.fraunhofer.de/tc-example-server:cache"] - cache-from = ["registry.netsec.aisec.fraunhofer.de/tc-example-server:cache"] - platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7"] -} - -target "example-idscp-provider-app" { - output = ["type=registry"] - cache-to = ["registry.netsec.aisec.fraunhofer.de/tc-example-client:cache"] - cache-from = ["registry.netsec.aisec.fraunhofer.de/tc-example-client:cache"] - platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7"] -} +//target "tpmsim" { +// output = ["type=registry"] +//// cache-to = ["registry.netsec.aisec.fraunhofer.de/tc-tpmsim:cache"] +//// cache-from = ["registry.netsec.aisec.fraunhofer.de/tc-tpmsim:cache"] +// platforms = ["linux/amd64", "linux/arm64/v8", "linux/arm/v7"] +//} \ No newline at end of file diff --git a/buildx/docker-bake.hcl b/buildx/docker-bake.hcl index ee0463639..4fe757424 100644 --- a/buildx/docker-bake.hcl +++ b/buildx/docker-bake.hcl @@ -1,7 +1,3 @@ -target "jdk-base" { - output = ["type=docker"] -} - target "build-container" { output = ["type=docker"] } @@ -10,18 +6,6 @@ target "core" { output = ["type=docker"] } -target "tpmsim" { - output = ["type=docker"] -} - -target "ttpsim" { - output = ["type=docker"] -} - -target "example-idscp-consumer-app" { - output = ["type=docker"] -} - -target "example-idscp-provider-app" { - output = ["type=docker"] -} \ No newline at end of file +//target "tpmsim" { +// output = ["type=docker"] +//} \ No newline at end of file diff --git a/buildx/docker-buildx.sh b/buildx/docker-buildx.sh old mode 100644 new mode 100755 index fe1ceee71..b241a7e52 --- a/buildx/docker-buildx.sh +++ b/buildx/docker-buildx.sh @@ -34,8 +34,8 @@ eval set -- "$PARSED" EXAMPLE_TAG_ARG="develop" DOCKER_BUILD_TAG_ARG="develop" -BASE_IMAGE_ARG="adoptopenjdk:11-jdk-hotspot" -TARGETS="core tpmsim ttpsim example-idscp-consumer-app example-idscp-provider-app" +BASE_IMAGE_ARG="adoptopenjdk:11-jdk-hotspot-focal" +TARGETS="core" FILES="" BUILD_CONTAINER=0 @@ -49,6 +49,10 @@ while true; do EXAMPLE_TAG_ARG="$2" shift 2 ;; + --targets) + TARGETS="$2" + shift 2 + ;; -b | --base-image) BASE_IMAGE_ARG="$2" shift 2 @@ -72,6 +76,9 @@ while true; do esac done +# Enable experimental Docker features (buildx) +export DOCKER_CLI_EXPERIMENTAL="enabled" + # Export vars for buildx bake yaml resolution export EXAMPLE_TAG="$EXAMPLE_TAG_ARG" export DOCKER_BUILD_TAG="$DOCKER_BUILD_TAG_ARG" @@ -79,8 +86,6 @@ export BASE_IMAGE="$BASE_IMAGE_ARG" printf "######################################################################\n" printf "Using build tag \"%s\" and base image \"%s\"\n" "$EXAMPLE_TAG" "$BASE_IMAGE" printf "######################################################################\n\n" -echo "Building jdk-base via \"docker buildx bake jdk-base ${FILES}$*\"..." -eval "docker buildx bake jdk-base ${FILES}$*" if [ $BUILD_CONTAINER = 1 ]; then echo "Building build-container via \"docker buildx bake build-container $*\"..." diff --git a/buildx/docker-compose.yml b/buildx/docker-compose.yml index 90c75a0db..9c6e4061f 100644 --- a/buildx/docker-compose.yml +++ b/buildx/docker-compose.yml @@ -1,14 +1,6 @@ version: '3' services: - # Base image for other JDK-based images - jdk-base: - image: fraunhoferaisec/jdk-base:${DOCKER_BUILD_TAG:-develop} - build: - context: '../docker-jdk-base' - args: - BASE_IMAGE: ${BASE_IMAGE:-adoptopenjdk:11-jdk-hotspot} - # Trusted Connector build container build-container: image: fraunhoferaisec/docker-build:${DOCKER_BUILD_TAG:-develop} @@ -25,29 +17,8 @@ services: args: JDK_BASE_IMAGE: fraunhoferaisec/jdk-base:${DOCKER_BUILD_TAG:-develop} - # TPM simulator - tpmsim: - image: fraunhoferaisec/tpmsim:${EXAMPLE_TAG:-develop} - build: - context: '../examples/tpmsim' - - # Trusted third party (RAT repository) simulator - ttpsim: - image: fraunhoferaisec/ttpsim:${EXAMPLE_TAG:-develop} - build: - context: '../rat-repository' - args: - JDK_BASE_IMAGE: fraunhoferaisec/jdk-base:${DOCKER_BUILD_TAG:-develop} - VERSION: ${PROJECT_VERSION} - - # IDSCP example data app (REST consumer, displays web page) - example-idscp-consumer-app: - image: fraunhoferaisec/example-server:${EXAMPLE_TAG:-develop} - build: - context: '../examples/example-idscp/example-server' - - # IDSCP example data provider - example-idscp-provider-app: - image: fraunhoferaisec/example-client:${EXAMPLE_TAG:-develop} - build: - context: '../examples/example-idscp/example-client' \ No newline at end of file +# # TPM simulator +# tpmsim: +# image: fraunhoferaisec/tpmsim:${EXAMPLE_TAG:-develop} +# build: +# context: '../examples/tpmsim' \ No newline at end of file diff --git a/camel-ids/.classpath b/camel-ids/.classpath deleted file mode 100644 index 7657d3ee9..000000000 --- a/camel-ids/.classpath +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/camel-ids/.gitignore b/camel-ids/.gitignore deleted file mode 100644 index 2d5934877..000000000 --- a/camel-ids/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -configuration.db -/cp.txt -*.pyc -/.classpath -/.apt_generated/ -/socket/ diff --git a/camel-ids/DEVS.TXT b/camel-ids/DEVS.TXT deleted file mode 100644 index 3c8d586c0..000000000 --- a/camel-ids/DEVS.TXT +++ /dev/null @@ -1 +0,0 @@ -Based on (forked from) camel-ahc-ws/camel-websocket 6cfdf4214288854d2f91a0fbf407ee1df99a8a01 https://github.com/apache/camel/commit/6cfdf4214288854d2f91a0fbf407ee1df99a8a01 \ No newline at end of file diff --git a/camel-ids/README.md b/camel-ids/README.md deleted file mode 100644 index 7f1b95d58..000000000 --- a/camel-ids/README.md +++ /dev/null @@ -1 +0,0 @@ -The _camel-ids_ module adds IDSCP support to the integrated Camel deployment. It creates a Camel Component to make the IDSCP available while building Camel routes. IDSCP itself is contained in module _ids-comm_. diff --git a/camel-ids/bnd.bnd b/camel-ids/bnd.bnd deleted file mode 100644 index 5ea70404e..000000000 --- a/camel-ids/bnd.bnd +++ /dev/null @@ -1,11 +0,0 @@ -Bundle-Name: IDS :: Camel IDSCP Support -Bundle-Description: Camel IDS protocol support -Export-Package: de.fhg.camel.ids.server,\ - de.fhg.camel.ids.connectionmanagement,\ - de.fhg.camel.ids.client -Import-Package: \ - !org.checkerframework.checker.*,\ - * -DynamicImport-Package: \ - org.asynchttpclient.netty.*,\ - com.typesafe.netty.* diff --git a/camel-ids/build.gradle b/camel-ids/build.gradle deleted file mode 100644 index d6b8d30a9..000000000 --- a/camel-ids/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -description = 'Camel IDS Component' - -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - providedByBundle(project(':ids-comm')) { transitive = false } - - // Bill of Materials (BOM) for Camel - bom group: 'org.apache.camel', name: 'camel-parent', version: libraryVersions.camel - - providedByFeature group: 'org.apache.camel', name: 'camel-core', version: libraryVersions.camel - providedByFeature group: 'org.apache.camel', name: 'camel-ahc', version: libraryVersions.camel - - providedByFeature group: 'org.eclipse.jetty', name: 'jetty-servlet', version: libraryVersions.jetty - providedByFeature group: 'org.eclipse.jetty', name: 'jetty-jmx', version: libraryVersions.jetty - providedByFeature group: 'org.eclipse.jetty', name: 'jetty-servlets', version: libraryVersions.jetty - - providedByFeature group: 'org.eclipse.jetty.websocket', name: 'websocket-server', version: libraryVersions.jetty - providedByFeature group: 'org.eclipse.jetty.websocket', name: 'websocket-client', version: libraryVersions.jetty - - compileOnly group: 'org.checkerframework', name: 'checker-qual', version: libraryVersions.checkerQual - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - osgiCore group: 'org.osgi', name: 'osgi.cmpn', version: libraryVersions.osgiCompendium - osgiCore group: 'org.osgi', name: 'org.osgi.core', version: libraryVersions.osgi - - providedByFeature group: 'com.google.protobuf', name: 'protobuf-java', version: libraryVersions.protobuf - - testImplementation group: 'junit', name: 'junit' - testImplementation group: 'org.apache.camel', name: 'camel-test', version: libraryVersions.camel - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/CamelComponent.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/CamelComponent.java deleted file mode 100644 index a632efd4a..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/CamelComponent.java +++ /dev/null @@ -1,123 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids; - -import de.fhg.aisec.ids.api.endpointconfig.EndpointConfigManager; -import de.fhg.aisec.ids.api.infomodel.InfoModel; -import de.fhg.aisec.ids.api.settings.Settings; -import de.fhg.aisec.ids.api.tokenm.TokenManager; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.osgi.service.component.annotations.*; - -@Component -public class CamelComponent { - - @Reference(cardinality = ReferenceCardinality.MANDATORY) - private Settings settings = null; - - @Reference(cardinality = ReferenceCardinality.MANDATORY) - private InfoModel infoModelManager = null; - - @Reference(cardinality = ReferenceCardinality.OPTIONAL) - private TokenManager tokenManager = null; - - @Reference(cardinality = ReferenceCardinality.OPTIONAL) - private EndpointConfigManager endpointConfigManager = null; - - private static CamelComponent instance; - - @Activate - @SuppressWarnings("squid:S2696") - protected void activate() { - instance = this; - } - - @Deactivate - @SuppressWarnings("squid:S2696") - protected void deactivate() { - instance = null; - } - - @Nullable - public static Settings getSettings() { - CamelComponent in = instance; - if (in != null) { - return in.settings; - } - return null; - } - - /** - * Is actually NonNull due to ReferenceCardinality.MANDATORY, - * but instance might be null for Unit Tests - * @return Info-Model-Manager instance - */ - @Nullable - public static InfoModel getInfoModelManager() { - CamelComponent in = instance; - if (in != null) { - return in.infoModelManager; - } - return null; - } - - /** - * Is actually NonNull due to ReferenceCardinality.MANDATORY, - * but instance might be null for Unit Tests - * @return Token-Manager instance - */ - @Nullable - public static TokenManager getTokenManager() { - CamelComponent in = instance; - if (in != null) { - return in.tokenManager; - } - return null; - } - - @Nullable - public static EndpointConfigManager getEndpointConfigManager() { - CamelComponent in = instance; - if (in != null) { - return in.endpointConfigManager; - } - return null; - } - - public void setSettings(Settings settings) { - this.settings = settings; - } - - public void setInfoModelManager(InfoModel infoModelManager) { - this.infoModelManager = infoModelManager; - } - - public void setTokenManager(TokenManager tokenManager) { - this.tokenManager = tokenManager; - } - - public void setEndpointConfigManager(EndpointConfigManager endpointConfigManager) { - this.endpointConfigManager = endpointConfigManager; - } - - public static void setInstance(CamelComponent instance) { - CamelComponent.instance = instance; - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/ProxyX509TrustManager.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/ProxyX509TrustManager.java deleted file mode 100644 index 5ee731365..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/ProxyX509TrustManager.java +++ /dev/null @@ -1,107 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids; - -import de.fhg.aisec.ids.comm.CertificatePair; -import org.apache.camel.support.jsse.*; - -import javax.net.ssl.X509TrustManager; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Enumeration; - -public class ProxyX509TrustManager implements X509TrustManager { - - public static void bindCertificatePair( - SSLContextParameters sslContextParameters, boolean isServer, CertificatePair certificatePair) - throws GeneralSecurityException, IOException { - // Acquire the local certificate - if (sslContextParameters.getKeyManagers() != null) { - KeyManagersParameters keyManagers = sslContextParameters.getKeyManagers(); - if (keyManagers.getKeyStore() != null) { - KeyStoreParameters keyStoreParameters = keyManagers.getKeyStore(); - KeyStore keyStore = keyStoreParameters.createKeyStore(); - // If a certificate alias is set, use it - String alias = sslContextParameters.getCertAlias(); - - // Otherwise, the first alias with a private key is relevant for us - if (alias == null) { - Enumeration es = keyStore.aliases(); - while (es.hasMoreElements()) { - alias = es.nextElement(); - if (keyStore.isKeyEntry(alias)) { - break; - } - } - } - // Now assign the certificate from the key store to the pair - if (alias != null) { - certificatePair.setLocalCertificate(keyStore.getCertificate(alias)); - } - } - } - // Acquire the remote server certificate OR just configure the server - if (isServer) { - // SERVER ONLY: Configure server to ask for client certificates - SSLContextServerParameters serverParameters = sslContextParameters.getServerParameters(); - if (serverParameters == null) { - serverParameters = new SSLContextServerParameters(); - } - serverParameters.setClientAuthentication("WANT"); - sslContextParameters.setServerParameters(serverParameters); - } else { - // CLIENT ONLY: Replace X509TrustManager with this proxy implementation to log certificate of - // remote server - TrustManagersParameters tmParams = sslContextParameters.getTrustManagers(); - X509TrustManager systemTrustManager = (X509TrustManager) tmParams.createTrustManagers()[0]; - tmParams.setTrustManager(new ProxyX509TrustManager(systemTrustManager, certificatePair)); - } - } - - private final X509TrustManager trustManager; - private final CertificatePair certificatePair; - - public ProxyX509TrustManager(X509TrustManager trustManager, CertificatePair certificatePair) { - this.trustManager = trustManager; - this.certificatePair = certificatePair; - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - trustManager.checkClientTrusted(chain, authType); - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - // Save observed server certificate - certificatePair.setRemoteCertificate(chain[0]); - trustManager.checkServerTrusted(chain, authType); - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return trustManager.getAcceptedIssuers(); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsComponent.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsComponent.java deleted file mode 100644 index af1d6cf66..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsComponent.java +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.client; - -import static de.fhg.aisec.ids.camel.ids.server.WebsocketConstants.WSS_PROTOCOL; -import static de.fhg.aisec.ids.camel.ids.server.WebsocketConstants.WS_PROTOCOL; - -import java.net.URI; -import org.apache.camel.component.ahc.AhcComponent; -import org.apache.camel.component.ahc.AhcEndpoint; - -public class WsComponent extends AhcComponent { - - @Override - protected String createAddressUri(String uri, String remaining) { - if (uri.startsWith("idsclientplain:")) { - return uri.replaceFirst("idsclientplain", WS_PROTOCOL); - } else if (uri.startsWith("idsclient:")) { - return uri.replaceFirst("idsclient", WSS_PROTOCOL); - } - // Should not happen - return uri; - } - - @Override - protected AhcEndpoint createAhcEndpoint(String endpointUri, AhcComponent component, URI httpUri) { - return new WsEndpoint(endpointUri, (WsComponent) component); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsConstants.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsConstants.java deleted file mode 100644 index 4d174c618..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsConstants.java +++ /dev/null @@ -1,33 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.client; - -/** */ -public final class WsConstants { - - public static final String CONTENT_TYPE_JAVA_SERIALIZED_OBJECT = - "application/x-java-serialized-object"; - public static final String CONTENT_TYPE_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded"; - - public static final String WS_PROTOCOL = "idsclientplain"; - public static final String WSS_PROTOCOL = "idsclient"; - - private WsConstants() {} -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsConsumer.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsConsumer.java deleted file mode 100644 index 2a719a34d..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsConsumer.java +++ /dev/null @@ -1,105 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.client; - -import org.apache.camel.Exchange; -import org.apache.camel.Processor; -import org.apache.camel.support.DefaultConsumer; - -import java.io.InputStream; -import java.io.Reader; - -/** - * A camel consumer retrieves an message, wraps in a Camel Exchange object and feeds it into Camel. - * - *

This is basically the implementation of a web socket server which accepts messages and sends - * them to Camel. - * - * @author Julian Schütte (julian.schuette@aisec.fraunhofer.de) - */ -public class WsConsumer extends DefaultConsumer { - - public WsConsumer(WsEndpoint endpoint, Processor processor) { - super(endpoint, processor); - } - - @Override - public void start() { - super.start(); - getEndpoint().connect(this); - } - - @Override - public void stop() { - getEndpoint().disconnect(this); - super.stop(); - } - - @Override - public WsEndpoint getEndpoint() { - return (WsEndpoint) super.getEndpoint(); - } - - public void sendMessage(String message) { - sendMessageInternal(message); - } - - public void sendMessage(Throwable throwable) { - sendMessageInternal(throwable); - } - - public void sendMessage(byte[] message) { - sendMessageInternal(message); - } - - public void sendMessage(InputStream message) { - sendMessageInternal(message); - } - - public void sendMessage(Reader message) { - sendMessageInternal(message); - } - - private void sendMessageInternal(Object message) { - final Exchange exchange = getEndpoint().createExchange(); - - // TODO may set some headers with some meta info (e.g., socket info, unique-id for correlation - // purpose, etc0 - // set the body - - if (message instanceof Throwable) { - exchange.setException((Throwable) message); - } else { - exchange.getIn().setBody(message); - } - - // send exchange using the async routing engine - getAsyncProcessor() - .process( - exchange, - doneSync -> { - if (exchange.getException() != null) { - getExceptionHandler() - .handleException( - "Error processing exchange", exchange, exchange.getException()); - } - }); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsEndpoint.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsEndpoint.java deleted file mode 100644 index bb5c168dc..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsEndpoint.java +++ /dev/null @@ -1,322 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.client; - -import de.fhg.aisec.ids.api.conm.IDSCPOutgoingConnection; -import de.fhg.aisec.ids.api.infomodel.InfoModel; -import de.fhg.aisec.ids.api.settings.Settings; -import de.fhg.aisec.ids.camel.ids.CamelComponent; -import de.fhg.aisec.ids.camel.ids.ProxyX509TrustManager; -import de.fhg.aisec.ids.camel.ids.server.WebsocketConstants; -import de.fhg.aisec.ids.comm.CertificatePair; -import de.fhg.aisec.ids.comm.client.ClientConfiguration; -import de.fhg.aisec.ids.comm.client.IdspClientSocket; -import de.fhg.aisec.ids.comm.ws.protocol.IDSCPException; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import org.apache.camel.Consumer; -import org.apache.camel.Processor; -import org.apache.camel.Producer; -import org.apache.camel.component.ahc.AhcEndpoint; -import org.apache.camel.spi.UriEndpoint; -import org.apache.camel.spi.UriParam; -import org.apache.camel.support.jsse.SSLContextParameters; -import org.asynchttpclient.*; -import org.asynchttpclient.ws.WebSocket; -import org.asynchttpclient.ws.WebSocketUpgradeHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.GeneralSecurityException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -/** - * This is the client-side implementation of a Camel endpoint for the IDS communication protocol - * (IDCP). - * - *

It is based on camel-ahc, further info is available at: Async Http Client. - */ -@UriEndpoint( - scheme = "idsclientplain,idsclient", - extendsScheme = "ahc,ahc", - title = "IDS Protocol", - syntax = "idsclient:httpUri", - consumerClass = WsConsumer.class, - label = "websocket" -) -public class WsEndpoint extends AhcEndpoint { - private static final Logger LOG = LoggerFactory.getLogger(WsEndpoint.class); - - private static List outgoingConnections = new ArrayList<>(); - - private final Set consumers = new HashSet<>(); - private final WsListener listener = new WsListener(consumers, this); - private WebSocket websocket; - private CertificatePair certificatePair = new CertificatePair(); - - @UriParam(label = "producer") - private boolean useStreaming; - - @UriParam(label = "consumer") - private boolean sendMessageOnError; - - @UriParam( - label = "attestation", - defaultValue = "0", - description = - "defines the remote attestation mode: 0=BASIC, 1=ALL, 2=ADVANCED, 3=ZERO. default value is 0=BASIC. (see api/attestation.proto for more details)" - ) - private int attestation = IdsAttestationType.BASIC.getNumber(); - - @UriParam( - label = "attestationMask", - defaultValue = "0", - description = - "defines the upper boundary of PCR values tested in ADVANCED mode. i.e. attestationMask=5 means values PCR0, PCR1, PCR2, PCR3 and PCR4" - ) - private Integer attestationMask = 0; - - public WsEndpoint(String endpointUri, WsComponent component) { - super(endpointUri, component, null); - } - - @Override - public void setSslContextParameters(SSLContextParameters sslContextParameters) { - if (sslContextParameters != null) { - try { - ProxyX509TrustManager.bindCertificatePair(sslContextParameters, false, certificatePair); - } catch (GeneralSecurityException | IOException e) { - LOG.error("Failed to patch TrustManager for WsEndpoint", e); - } - } - super.setSslContextParameters(sslContextParameters); - } - - @Override - public WsComponent getComponent() { - return (WsComponent) super.getComponent(); - } - - @Override - public Producer createProducer() { - return new WsProducer(this); - } - - @Override - public Consumer createConsumer(Processor processor) { - return new WsConsumer(this, processor); - } - - public static List getOutgoingConnections() { - return outgoingConnections; - } - - WebSocket getWebSocket() { - synchronized (this) { - // ensure we are connected - reConnect(); - } - return websocket; - } - - void setWebSocket(WebSocket websocket) { - this.websocket = websocket; - } - - public boolean isUseStreaming() { - return useStreaming; - } - - /** To enable streaming to send data as multiple text fragments. */ - public void setUseStreaming(boolean useStreaming) { - this.useStreaming = useStreaming; - } - - public boolean isSendMessageOnError() { - return sendMessageOnError; - } - - public void setAttestation(int type) { - this.attestation = type; - } - - public int getAttestation() { - return attestation; - } - - public void setAttestationMask(int type) { - this.attestationMask = type; - } - - public int getAttestationMask() { - return attestationMask; - } - - /** Whether to send an message if the web-socket listener received an error. */ - public void setSendMessageOnError(boolean sendMessageOnError) { - this.sendMessageOnError = sendMessageOnError; - } - - @Override - protected AsyncHttpClient createClient(AsyncHttpClientConfig config) { - if (config == null) { - config = new DefaultAsyncHttpClientConfig.Builder().build(); - } - return new DefaultAsyncHttpClient(config); - } - - public void connect() { - String uri = getHttpUri().toASCIIString(); - if (uri.startsWith("idsclient:")) { - uri = uri.replaceFirst("idsclient", WebsocketConstants.WSS_PROTOCOL); - } else if (uri.startsWith("idsclientplain:")) { - uri = uri.replaceFirst("idsclientplain", WebsocketConstants.WS_PROTOCOL); - } - - LOG.debug("Connecting to {}", uri); - BoundRequestBuilder reqBuilder = - getClient().prepareGet(uri).addHeader("Sec-WebSocket-Protocol", "ids"); - - LOG.debug("remote-attestation mode: {}", this.getAttestation()); - LOG.debug("remote-attestation mask: {}", this.getAttestationMask()); - - // Execute IDS protocol immediately after connect - Settings settings = CamelComponent.getSettings(); - URI ttpUri = null; - try { - if (settings != null) { - ttpUri = - new URI( - String.format( - "https://%s:%d/rat-verify", - settings.getConnectorConfig().getTtpHost(), - settings.getConnectorConfig().getTtpPort())); - } - } catch (URISyntaxException e) { - LOG.error("incorrect TTP URI syntax", e); - } - InfoModel infoModelManager = CamelComponent.getInfoModelManager(); - ClientConfiguration.Builder clientConfigBuilder = - new ClientConfiguration.Builder() - .attestationType(IdsAttestationType.forNumber(this.getAttestation())) - .attestationMask(this.getAttestationMask()) - .certificatePair(certificatePair) - .ttpUrl(ttpUri); - if (infoModelManager == null) { - clientConfigBuilder - .rdfDescription("{\"message\":\"Infomodel is not available\"}") - .dynamicAttributeToken("{\"message\":\"DAPS token is not available\"}"); - } else { - try { - clientConfigBuilder.rdfDescription(infoModelManager.getConnectorAsJsonLd()); - } catch (Exception x) { - LOG.error("Infomodel load failed, please configure a valid Infomodel via the REST API!"); - clientConfigBuilder.rdfDescription("{\"message\":\"Infomodel is not available\"}"); - } - try { - clientConfigBuilder.dynamicAttributeToken(infoModelManager.getDynamicAttributeToken()); - } catch (Exception x) { - LOG.error("DAPS token load failed, please verify your DAPS configuration!"); - clientConfigBuilder.dynamicAttributeToken("{\"message\":\"DAPS token is not available\"}"); - } - } - IdspClientSocket idspListener = new IdspClientSocket(clientConfigBuilder.build()); - - try { - // Block until IDSCP has finished - idspListener.semaphore().lockInterruptibly(); - - websocket = - reqBuilder - .execute( - new WebSocketUpgradeHandler.Builder().addWebSocketListener(idspListener).build()) - .get(); - - do { - try { - if (idspListener.idscpInProgressCondition().await(30, TimeUnit.SECONDS)) { - break; - } - } catch (InterruptedException ie) { - LOG.warn("Interrupt occurred whilst waiting for IDSCP handshake", ie); - Thread.currentThread().interrupt(); - } - } while (!idspListener.isTerminated()); // To handle sporadic wake-ups - } catch (ExecutionException | InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IDSCPException("Error in WebSocket connect", e); - } finally { - idspListener.semaphore().unlock(); - } - // get remote address, get upgrade headers, instantiate ConnectionManagerService to register - // websocket - // When IDS protocol has finished, hand over to normal web socket listener - websocket.addWebSocketListener(listener); - websocket.removeWebSocketListener(idspListener); - - // Add Client Endpoint information to static List - IDSCPOutgoingConnection ce = new IDSCPOutgoingConnection(); - ce.setAttestationResult(idspListener.getAttestationResult()); - ce.setMetaData(idspListener.getMetaResult()); - ce.setEndpointIdentifier(this.getEndpointUri()); - ce.setEndpointKey(this.getEndpointKey()); - ce.setRemoteIdentity(websocket.getRemoteAddress().toString()); - outgoingConnections.add(ce); - } - - @Override - protected void doStop() throws Exception { - if (websocket != null && websocket.isOpen()) { - if (LOG.isDebugEnabled()) { - LOG.debug("Disconnecting from {}", getHttpUri().toASCIIString()); - } - websocket.removeWebSocketListener(listener); - websocket.sendCloseFrame(); - websocket = null; - } - outgoingConnections.removeIf(ic -> ic.getEndpointKey().equals(this.getEndpointKey())); - super.doStop(); - } - - void connect(WsConsumer wsConsumer) { - consumers.add(wsConsumer); - //reConnect(); - } - - void disconnect(WsConsumer wsConsumer) { - consumers.remove(wsConsumer); - } - - void reConnect() { - if (websocket == null || !websocket.isOpen()) { - String uri = getHttpUri().toASCIIString(); - LOG.info("Reconnecting websocket: {}", uri); - connect(); - } - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsListener.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsListener.java deleted file mode 100644 index 5cd6cc522..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsListener.java +++ /dev/null @@ -1,83 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.client; - -import java.util.Set; -import org.asynchttpclient.ws.WebSocket; -import org.asynchttpclient.ws.WebSocketListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class WsListener implements WebSocketListener { - private static final Logger LOG = LoggerFactory.getLogger(WsListener.class); - - private final Set consumers; - private final WsEndpoint endpoint; - - public WsListener(Set consumers, WsEndpoint endpoint) { - this.consumers = consumers; - this.endpoint = endpoint; - } - - @Override - public void onOpen(WebSocket websocket) { - LOG.debug("Websocket opened"); - } - - @Override - public void onClose(WebSocket websocket, int code, String status) { - if (code == 1003){ - LOG.debug("websocket closed - " + status); - } else { - LOG.debug("websocket closed - reconnecting"); - try { - this.endpoint.reConnect(); - } catch (Exception e) { - LOG.warn("Error re-connecting to websocket", e); - } - } - } - - @Override - public void onError(Throwable t) { - LOG.debug("websocket on error", t); - if (endpoint.isSendMessageOnError()) { - for (WsConsumer consumer : consumers) { - consumer.sendMessage(t); - } - } - } - - @Override - public void onBinaryFrame(byte[] message, boolean finalFragment, int rsv) { - LOG.debug("Received message --> {}", message); - for (WsConsumer consumer : consumers) { - consumer.sendMessage(message); - } - } - - @Override - public void onTextFrame(String message, boolean finalFragment, int rsv) { - LOG.debug("Received message --> {}", message); - for (WsConsumer consumer : consumers) { - consumer.sendMessage(message); - } - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsProducer.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsProducer.java deleted file mode 100644 index 0301aec74..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/client/WsProducer.java +++ /dev/null @@ -1,138 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.client; - -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.apache.camel.support.DefaultProducer; -import org.asynchttpclient.ws.WebSocket; - -import java.io.IOException; -import java.io.InputStream; - -/** */ -public class WsProducer extends DefaultProducer { - private static final int DEFAULT_STREAM_BUFFER_SIZE = 127; - - private int streamBufferSize = DEFAULT_STREAM_BUFFER_SIZE; - - public WsProducer(WsEndpoint endpoint) { - super(endpoint); - } - - @Override - public WsEndpoint getEndpoint() { - return (WsEndpoint) super.getEndpoint(); - } - - @Override - public void process(Exchange exchange) throws Exception { - Message in = exchange.getIn(); - Object message = in.getBody(); - if (message != null) { - if (log.isTraceEnabled()) { - log.debug("Sending out {}", message); - } - if (message instanceof String) { - sendMessage(getWebSocket(), (String) message, getEndpoint().isUseStreaming()); - } else if (message instanceof byte[]) { - sendMessage(getWebSocket(), (byte[]) message, getEndpoint().isUseStreaming()); - } else if (message instanceof InputStream) { - sendStreamMessage(getWebSocket(), (InputStream) message); - } else { - // TODO provide other binding option, for now use the converted string - getWebSocket().sendTextFrame(in.getMandatoryBody(String.class)); - } - } - } - - private void sendMessage(WebSocket webSocket, String msg, boolean streaming) { - if (streaming) { - int p = 0; - while (p < msg.length()) { - if (msg.length() - p < streamBufferSize) { - webSocket.sendContinuationFrame(msg.substring(p), true, 0); - p = msg.length(); - } else { - webSocket.sendContinuationFrame(msg.substring(p, streamBufferSize), false, 0); - p += streamBufferSize; - } - } - } else { - webSocket.sendTextFrame(msg); - } - } - - private void sendMessage(WebSocket webSocket, byte[] msg, boolean streaming) { - if (streaming) { - int p = 0; - byte[] writebuf = new byte[streamBufferSize]; - while (p < msg.length) { - if (msg.length - p < streamBufferSize) { - int rest = msg.length - p; - // bug in grizzly? we need to create a byte array with the exact length - // webSocket.stream(msg, p, rest, true); - System.arraycopy(msg, p, writebuf, 0, rest); - byte[] tmpbuf = new byte[rest]; - System.arraycopy(writebuf, 0, tmpbuf, 0, rest); - webSocket.sendContinuationFrame(tmpbuf, false, 0); - // ends - p = msg.length; - } else { - // bug in grizzly? we need to create a byte array with the exact length - // webSocket.stream(msg, p, streamBufferSize, false); - System.arraycopy(msg, p, writebuf, 0, streamBufferSize); - webSocket.sendContinuationFrame(writebuf, false, 0); - // ends - p += streamBufferSize; - } - } - } else { - webSocket.sendBinaryFrame(msg); - } - } - - private void sendStreamMessage(WebSocket webSocket, InputStream in) throws IOException { - byte[] readbuf = new byte[streamBufferSize]; - byte[] writebuf = new byte[streamBufferSize]; - int rn; - int wn = 0; - try (in) { - while ((rn = in.read(readbuf, 0, readbuf.length)) != -1) { - if (wn > 0) { - webSocket.sendContinuationFrame(writebuf, false, 0); - } - System.arraycopy(readbuf, 0, writebuf, 0, rn); - wn = rn; - } - // a bug in grizzly? we need to create a byte array with the exact length - if (wn < writebuf.length) { - byte[] tmpbuf = writebuf; - writebuf = new byte[wn]; - System.arraycopy(tmpbuf, 0, writebuf, 0, wn); - } // ends - webSocket.sendContinuationFrame(writebuf, true, 0); - } - } - - private WebSocket getWebSocket() { - return getEndpoint().getWebSocket(); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/connectionmanagement/ConnectionManagerService.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/connectionmanagement/ConnectionManagerService.java deleted file mode 100644 index 78d7a4ae2..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/connectionmanagement/ConnectionManagerService.java +++ /dev/null @@ -1,104 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.connectionmanagement; - -import de.fhg.aisec.ids.api.conm.ConnectionManager; -import de.fhg.aisec.ids.api.conm.IDSCPIncomingConnection; -import de.fhg.aisec.ids.api.conm.IDSCPOutgoingConnection; -import de.fhg.aisec.ids.api.conm.IDSCPServerEndpoint; -import de.fhg.aisec.ids.api.settings.Settings; -import de.fhg.aisec.ids.camel.ids.client.WsEndpoint; -import de.fhg.aisec.ids.camel.ids.server.WebsocketComponent; -import de.fhg.aisec.ids.camel.ids.server.WebsocketComponentServlet; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.osgi.service.component.annotations.*; - -/** - * Main entry point of the Connection Management Layer. - * - *

This class is exposed as an OSGi Service and serves to access connection data from the - * management layer and REST API. - * - * @author Gerd Brost(gerd.brost@aisec.fraunhofer.de) - */ -@Component(name = "ids-connection-manager", immediate = true) -public class ConnectionManagerService implements ConnectionManager { - - @Override - public List listAvailableEndpoints() { - return WebsocketComponent.getConnectors() - .entrySet() - .stream() - .map( - cEntry -> { - IDSCPServerEndpoint endpoint = new IDSCPServerEndpoint(); - endpoint.setHost(cEntry.getValue().getConnector().getHost()); - endpoint.setPort(Integer.toString(cEntry.getValue().getConnector().getPort())); - endpoint.setDefaultProtocol(cEntry.getValue().getConnector().getDefaultProtocol()); - endpoint.setEndpointIdentifier(cEntry.getKey()); - return endpoint; - }) - .collect(Collectors.toList()); - } - - @Override - public List listIncomingConnections() { - return WebsocketComponent.getConnectors() - .values() - .stream() - .flatMap( - connectorRef -> { - WebsocketComponentServlet servlet = connectorRef.getServlet(); - // Servlet only present if an incoming connection exists. If null, do not collect - // consumer information. - if (servlet != null) { - // Every connection has a websocket. We collect connection information this way. - return connectorRef - .getMemoryStore() - .getAll() - .stream() - .map( - dws -> { - IDSCPIncomingConnection incomingConnection = - new IDSCPIncomingConnection(); - incomingConnection.setEndpointIdentifier( - servlet.getConsumer().getEndpoint().toString()); - incomingConnection.setEndpointKey(dws.getConnectionKey()); - incomingConnection.setRemoteHostName(dws.getRemoteHostname()); - incomingConnection.setAttestationResult(dws.getAttestationResult()); - incomingConnection.setMetaData(dws.getMetaResult()); - incomingConnection.setDynamicAttributeToken( - dws.getDynamicAttributeToken()); - return incomingConnection; - }); - } else { - return Stream.empty(); - } - }) - .collect(Collectors.toList()); - } - - @Override - public List listOutgoingConnections() { - return WsEndpoint.getOutgoingConnections(); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/ConnectorRef.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/ConnectorRef.java deleted file mode 100644 index f2b2318fd..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/ConnectorRef.java +++ /dev/null @@ -1,71 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; - -public class ConnectorRef { - Server server; - ServerConnector connector; - WebsocketComponentServlet servlet; - MemoryWebsocketStore memoryStore; - int refCount; - - ConnectorRef( - Server server, - ServerConnector connector, - WebsocketComponentServlet servlet, - MemoryWebsocketStore memoryStore) { - this.server = server; - this.connector = connector; - this.servlet = servlet; - this.memoryStore = memoryStore; - increment(); - } - - public int increment() { - return ++refCount; - } - - public int decrement() { - return --refCount; - } - - public int getRefCount() { - return refCount; - } - - public Server getServer() { - return this.server; - } - - public ServerConnector getConnector() { - return this.connector; - } - - public WebsocketComponentServlet getServlet() { - return this.servlet; - } - - public MemoryWebsocketStore getMemoryStore() { - return this.memoryStore; - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/DefaultNodeSynchronization.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/DefaultNodeSynchronization.java deleted file mode 100644 index 78a120ba8..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/DefaultNodeSynchronization.java +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -public class DefaultNodeSynchronization implements NodeSynchronization { - - private final WebsocketStore memoryStore; - - public DefaultNodeSynchronization(WebsocketStore memoryStore) { - this.memoryStore = memoryStore; - } - - @Override - public void addSocket(DefaultWebsocket socket) { - memoryStore.add(socket); - } - - @Override - public void removeSocket(String id) { - memoryStore.remove(id); - } - - @Override - public void removeSocket(DefaultWebsocket socket) { - memoryStore.remove(socket); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/DefaultWebsocket.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/DefaultWebsocket.java deleted file mode 100644 index d55f1e50f..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/DefaultWebsocket.java +++ /dev/null @@ -1,306 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import com.google.protobuf.InvalidProtocolBufferException; -import de.fhg.aisec.ids.api.conm.RatResult; -import de.fhg.aisec.ids.api.endpointconfig.EndpointConfigListener; -import de.fhg.aisec.ids.api.endpointconfig.EndpointConfigManager; -import de.fhg.aisec.ids.api.infomodel.InfoModel; -import de.fhg.aisec.ids.api.settings.ConnectionSettings; -import de.fhg.aisec.ids.api.settings.Settings; -import de.fhg.aisec.ids.api.tokenm.TokenManager; -import de.fhg.aisec.ids.camel.ids.CamelComponent; -import de.fhg.aisec.ids.api.tokenm.DatException; -import de.fhg.aisec.ids.comm.CertificatePair; -import de.fhg.aisec.ids.comm.server.ServerConfiguration; -import de.fhg.aisec.ids.comm.ws.protocol.ProtocolState; -import de.fhg.aisec.ids.comm.ws.protocol.ServerProtocolMachine; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.FSM; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.eclipse.jetty.websocket.api.CloseStatus; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.annotations.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.util.UUID; - -@WebSocket -public class DefaultWebsocket implements EndpointConfigListener { - private static final Logger LOG = LoggerFactory.getLogger(DefaultWebsocket.class); - - private final WebsocketConsumer consumer; - private final NodeSynchronization sync; - private Session session; - private String connectionKey; - private final String pathSpec; - private FSM idsFsm; - private CertificatePair certificatePair; - private boolean isTokenValidated = false; - - public DefaultWebsocket( - NodeSynchronization sync, - String pathSpec, - WebsocketConsumer consumer, - CertificatePair certificatePair) { - this.sync = sync; - this.consumer = consumer; - this.pathSpec = pathSpec; - this.certificatePair = certificatePair; - } - - @OnWebSocketClose - public void onClose(int closeCode, String message) { - if (LOG.isTraceEnabled()) { - LOG.trace("onClose {} {}", closeCode, message); - } - sync.removeSocket(this); - - // Remove Listener from EndpointConfigManager - final EndpointConfigManager ecp = CamelComponent.getEndpointConfigManager(); - if (ecp != null) { - if (LOG.isDebugEnabled()) { - LOG.debug("Remove EndpointConfigListener: {}", this); - } - String endpointIdentifier = consumer.getEndpoint().getHost() + ":" + consumer.getEndpoint().getPort(); - ecp.removeEndpointConfigListener(endpointIdentifier); - } - } - - @OnWebSocketConnect - public void onConnect(Session session) { - if (LOG.isTraceEnabled()) { - LOG.trace("onConnect {}", session); - } - this.session = session; - this.connectionKey = UUID.randomUUID().toString(); - IdsAttestationType type; - int attestationMask = 0; - switch (this.consumer.getAttestationType()) { - case 1: - type = IdsAttestationType.ALL; - break; - case 2: - type = IdsAttestationType.ADVANCED; - attestationMask = this.consumer.getAttestationMask(); - break; - case 0: - default: - type = IdsAttestationType.BASIC; - } - // Integrate server-side of IDS protocol - Settings settings = CamelComponent.getSettings(); - URI ttpUri = null; - try { - if (settings != null) { - ttpUri = - new URI( - String.format( - "https://%s:%d/rat-verify", - settings.getConnectorConfig().getTtpHost(), - settings.getConnectorConfig().getTtpPort())); - } - } catch (URISyntaxException e) { - LOG.error("incorrect TTP URI syntax", e); - } - InfoModel infoModelManager = CamelComponent.getInfoModelManager(); - ServerConfiguration.Builder serverConfigBuilder = - new ServerConfiguration.Builder() - .attestationType(type) - .attestationMask(attestationMask) - .certificatePair(certificatePair) - .ttpUrl(ttpUri); - if (infoModelManager == null) { - serverConfigBuilder - .rdfDescription("{\"message\":\"Infomodel is not available\"}") - .dynamicAttributeToken("{\"message\":\"DAPS token is not available\"}"); - } else { - try { - serverConfigBuilder.rdfDescription(infoModelManager.getConnectorAsJsonLd()); - } catch (Exception x) { - LOG.error("Infomodel load failed, please configure a valid Infomodel via the REST API!"); - serverConfigBuilder.rdfDescription("{\"message\":\"Infomodel is not available\"}"); - } - try { - serverConfigBuilder.dynamicAttributeToken(infoModelManager.getDynamicAttributeToken()); - } catch (Exception x) { - LOG.error("DAPS token load failed, please verify your DAPS configuration!"); - serverConfigBuilder.dynamicAttributeToken("{\"message\":\"DAPS token is not available\"}"); - } - } - idsFsm = new ServerProtocolMachine(session, serverConfigBuilder.build(), this::validateDynamicAttributeToken); - sync.addSocket(this); - - // Register listener at EndpointConfigManager - final EndpointConfigManager ecp = CamelComponent.getEndpointConfigManager(); - if (ecp != null) { - if (LOG.isDebugEnabled()) { - LOG.debug("Register EndpointConfigListener: {}", this); - } - String endpointIdentifier = consumer.getEndpoint().getHost() + ":" + consumer.getEndpoint().getPort(); - ecp.addEndpointConfigListener(endpointIdentifier, this); - } - } - - - @OnWebSocketMessage - public void onMessage(String message) { - LOG.debug("onMessage: {}", message); - // Check if fsm is in its final state If not, this message is not our department - if (idsFsm.getState().equals(ProtocolState.IDSCP_END.id())) { - if (this.consumer != null) { - this.consumer.sendMessage(this.connectionKey, message); - } else { - LOG.warn("No consumer to handle message received: {}", message); - } - return; - } - // Otherwise, we are still in the process of running IDS protocol and hold back the original - // message. In this case, feed the message into the protocol FSM - try { - ConnectorMessage msg = ConnectorMessage.parseFrom(message.getBytes()); - // we de-protobuf and split messages into cmd and payload - idsFsm.feedEvent(new Event(msg.getType(), message, msg)); - } catch (InvalidProtocolBufferException e) { - // An invalid message has been received during IDS protocol. close connection - LOG.error(e.getMessage(), e); - this.session.close(new CloseStatus(403, "invalid protobuf")); - } - } - - @OnWebSocketMessage - public void onMessage(byte[] data, int offset, int length) { - LOG.trace("server received {} byte in onMessage", length); - if (idsFsm.getState().equals(ProtocolState.IDSCP_END.id())) { - if (this.consumer != null) { - this.consumer.sendMessage(this.connectionKey, data); - } else { - LOG.debug("No consumer to handle message received: {}", data); - } - } else { - try { - ConnectorMessage msg = ConnectorMessage.parseFrom(data); - idsFsm.feedEvent( - new Event( - msg.getType(), - new String(data, StandardCharsets.UTF_8), - msg)); // we need to de-protobuf here and split messages into cmd and payload - } catch (IOException e) { - // An invalid message has been received during IDS protocol. close connection - LOG.error("Closing session because " + e.getMessage(), e); - this.session.close(new CloseStatus(403, "invalid protobuf")); - } - } - } - - @OnWebSocketError - public void onError(Session session, Throwable t) { - LOG.error(t.getMessage() + " Host: " + session.getRemoteAddress().getHostName(), t); - } - - private void validateDynamicAttributeToken(@NonNull String dat) throws DatException { - TokenManager tokenManager = CamelComponent.getTokenManager(); - assert tokenManager != null; - Settings settings = CamelComponent.getSettings(); - assert settings != null; - - String dapsUrl = settings.getConnectorConfig().getDapsUrl(); - - // Get endpoint security settings, never returns null - ConnectionSettings connectionSettings = settings.getConnectionSettings(consumer.getEndpoint().getHost() + ":" - + consumer.getEndpoint().getPort().toString()); - - // This is a bug in the DAPS. - // Audience should not be set to default value "IDS_Connector" - String targetAudience = "IDS_Connector"; - - try { - //validate token signature, target Audience, expire date - var claims = tokenManager.verifyJWT(dat, targetAudience, dapsUrl); - //validate supported security attributes - tokenManager.validateDATSecurityAttributes(claims, connectionSettings); - } catch (Exception e) { - throw new DatException("DAT verification failed!", e); - } - } - - public Session getSession() { - return session; - } - - public String getPathSpec() { - return pathSpec; - } - - public String getConnectionKey() { - return connectionKey; - } - - // get the result of the remote attestation - public RatResult getAttestationResult() { - return idsFsm.getRatResult(); - } - - public String getMetaResult() { - return idsFsm.getMetaData(); - } - - public String getDynamicAttributeToken() { - return idsFsm.getDynamicAttributeToken(); - } - - public String getRemoteHostname() { - return session.getRemoteAddress().getHostName(); - } - - // Observer update function, that is called by the subject when endpoint settings have changed - @Override - public void updateTokenValidation() { - if (!isTokenValidated) { - // Not relevant because initial validation was not successful yet - return; - } - - if (LOG.isInfoEnabled()) { - LOG.info("Endpoint config for endpoint {}:{} has changed. Verify DynamicAttributeToken again", - consumer.getEndpoint().getHost(), consumer.getEndpoint().getPort()); - } - - try { - validateDynamicAttributeToken(getDynamicAttributeToken()); - if (LOG.isInfoEnabled()) { - LOG.info("DynamicAttributeToken: Client validation was successful."); - } - } catch(DatException de) { - if (LOG.isInfoEnabled()) { - LOG.warn("DynamicAttributeToken: Client validation failed. Disconnecting from Client..."); - } - this.session.close(new CloseStatus(1003, "Security requirements not fulfilled anymore")); - } - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/DefaultWebsocketFactory.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/DefaultWebsocketFactory.java deleted file mode 100644 index 9390dc193..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/DefaultWebsocketFactory.java +++ /dev/null @@ -1,56 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import de.fhg.aisec.ids.comm.CertificatePair; -import java.security.cert.X509Certificate; -import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Default websocket factory. Used when no custom websocket is needed. */ -public class DefaultWebsocketFactory implements WebSocketFactory { - private static final Logger LOG = LoggerFactory.getLogger(DefaultWebsocketFactory.class); - - private final CertificatePair certificatePair; - - public DefaultWebsocketFactory(CertificatePair certificatePair) { - this.certificatePair = certificatePair; - } - - @Override - public DefaultWebsocket newInstance( - ServletUpgradeRequest request, - String protocol, - String pathSpec, - NodeSynchronization sync, - WebsocketConsumer consumer) { - // Create final, complete pair from the local (server) certificate ... - CertificatePair finalPair = new CertificatePair(certificatePair); - // ... plus the remote (client) certificate from the request - X509Certificate[] certificates = request.getCertificates(); - if (certificates != null && certificates.length > 0) { - finalPair.setRemoteCertificate(certificates[0]); - } else { - LOG.warn("Remote client did not present TLS certificate"); - } - return new DefaultWebsocket(sync, pathSpec, consumer, finalPair); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/JettyClassPathResource.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/JettyClassPathResource.java deleted file mode 100644 index 083f6ae2a..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/JettyClassPathResource.java +++ /dev/null @@ -1,130 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.nio.channels.ReadableByteChannel; -import org.apache.camel.spi.ClassResolver; -import org.apache.camel.util.IOHelper; -import org.apache.camel.util.ObjectHelper; -import org.eclipse.jetty.util.resource.Resource; - -/** - * A Jetty {@link Resource} to load from the classpath using Camels {@link ClassResolver} which - * ensures loading resources works in OSGi and other containers. - */ -public class JettyClassPathResource extends Resource { - - private final ClassResolver resolver; - private final String path; - - public JettyClassPathResource(ClassResolver resolver, String path) { - this.resolver = ObjectHelper.notNull(resolver, "ClassResolver"); - this.path = ObjectHelper.notNull(path, "path"); - } - - @Override - public boolean isContainedIn(Resource r) { - return false; - } - - @Override - public boolean exists() { - InputStream is = resolver.loadResourceAsStream(path); - if (is != null) { - IOHelper.close(is); - } - return is != null; - } - - @Override - public boolean isDirectory() { - return exists() && path.endsWith("/"); - } - - @Override - public long lastModified() { - return 0; - } - - @Override - public long length() { - return 0; - } - - @Override - @Deprecated - public URL getURL() { - return resolver.loadResourceAsURL(path); - } - - @Override - public File getFile() throws IOException { - URI uri = getURI(); - if (uri != null) { - return new File(uri.toURL().getFile()); - } - return null; - } - - @Override - public String getName() { - return path; - } - - @Override - public InputStream getInputStream() { - return resolver.loadResourceAsStream(path); - } - - @Override - public boolean delete() { - return false; - } - - @Override - public boolean renameTo(Resource dest) { - return false; - } - - @Override - public String[] list() { - return new String[0]; - } - - @Override - public Resource addPath(String path) { - return new JettyClassPathResource(resolver, this.path + "/" + path); - } - - @Override - public void close() { - // noop - } - - @Override - public ReadableByteChannel getReadableByteChannel() { - return null; - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/MemoryWebsocketStore.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/MemoryWebsocketStore.java deleted file mode 100644 index e4e4b9a36..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/MemoryWebsocketStore.java +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; - -public class MemoryWebsocketStore extends ConcurrentHashMap - implements WebsocketStore { - - private static final long serialVersionUID = -2826843758230613922L; - - @Override - public void add(DefaultWebsocket ws) { - super.put(getKey(ws), ws); - } - - @Override - public void remove(DefaultWebsocket ws) { - super.remove(getKey(ws)); - } - - @Override - public void remove(String key) { - super.remove(key); - } - - @Override - public DefaultWebsocket get(String key) { - return super.get(key); - } - - @Override - public Collection getAll() { - return super.values(); - } - - @Override - public void start() { - // noop - } - - @Override - public void stop() { - clear(); - } - - private String getKey(DefaultWebsocket ws) { - StringBuilder sb = new StringBuilder(); - if (ws.getConnectionKey() != null) { - sb.append(ws.getConnectionKey()); - } - if (ws.getPathSpec() != null) { - sb.append(ws.getPathSpec()); - } - return sb.toString(); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/NodeSynchronization.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/NodeSynchronization.java deleted file mode 100644 index 45caf0f3a..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/NodeSynchronization.java +++ /dev/null @@ -1,44 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -public interface NodeSynchronization { - - /** - * Adds the web socket to both (always if present) stores. - * - * @param socket the web socket - */ - void addSocket(DefaultWebsocket socket); - - /** - * Removes the Websocket from both stores - * - * @param id id of the web socket - */ - void removeSocket(String id); - - /** - * Removes the Websocket from both stores - * - * @param socket web socket to remove - */ - void removeSocket(DefaultWebsocket socket); -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebSocketFactory.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebSocketFactory.java deleted file mode 100644 index 7436e82d4..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebSocketFactory.java +++ /dev/null @@ -1,33 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; - -/** Web socket factory interface. */ -public interface WebSocketFactory { - - DefaultWebsocket newInstance( - ServletUpgradeRequest request, - String protocol, - String pathSpec, - NodeSynchronization sync, - WebsocketConsumer consumer); -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketComponent.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketComponent.java deleted file mode 100644 index 59e451d88..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketComponent.java +++ /dev/null @@ -1,726 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import de.fhg.aisec.ids.camel.ids.ProxyX509TrustManager; -import de.fhg.aisec.ids.comm.CertificatePair; -import org.apache.camel.Endpoint; -import org.apache.camel.RuntimeCamelException; -import org.apache.camel.SSLContextParametersAware; -import org.apache.camel.spi.Metadata; -import org.apache.camel.support.DefaultComponent; -import org.apache.camel.support.jsse.SSLContextParameters; -import org.eclipse.jetty.server.*; -import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.server.handler.HandlerCollection; -import org.eclipse.jetty.server.handler.HandlerWrapper; -import org.eclipse.jetty.server.session.SessionHandler; -import org.eclipse.jetty.servlet.DefaultServlet; -import org.eclipse.jetty.servlet.FilterHolder; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.servlets.CrossOriginFilter; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.eclipse.jetty.util.thread.ThreadPool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.DispatcherType; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -public class WebsocketComponent extends DefaultComponent implements SSLContextParametersAware { - protected static final Logger LOG = LoggerFactory.getLogger(WebsocketComponent.class); - protected static final Map CONNECTORS = new HashMap<>(); - - protected Map socketFactories; - private final CertificatePair certificatePair = new CertificatePair(); - - @Metadata(label = "security") - protected SSLContextParameters sslContextParameters; - - @Metadata(label = "security", defaultValue = "false") - protected boolean useGlobalSslContextParameters; - - @Metadata(label = "advanced") - protected ThreadPool threadPool; - - @Metadata(defaultValue = "9292") - protected Integer port = 9292; - - @Metadata(label = "advanced") - protected Integer minThreads; - - @Metadata(label = "advanced") - protected Integer maxThreads; - - @Metadata(defaultValue = "0.0.0.0") - protected String host = "0.0.0.0"; - - @Metadata(label = "consumer") - protected String staticResources; - - @Metadata(label = "security", secret = true) - protected String sslKeyPassword; - - @Metadata(label = "security", secret = true) - protected String sslPassword; - - @Metadata(label = "security", secret = true) - protected String sslKeystore; - - /** - * Map for storing servlets. {@link WebsocketComponentServlet} is identified by pathSpec {@link - * String}. - */ - private Map servlets = new HashMap<>(); - - public class ConnectorRef { - Server server; - ServerConnector connector; - WebsocketComponentServlet servlet; - MemoryWebsocketStore memoryStore; - AtomicInteger refCount = new AtomicInteger(1); - - ConnectorRef( - Server server, - ServerConnector connector, - WebsocketComponentServlet servlet, - MemoryWebsocketStore memoryStore) { - this.server = server; - this.connector = connector; - this.servlet = servlet; - this.memoryStore = memoryStore; - } - - public int increment() { - return refCount.incrementAndGet(); - } - - public int decrement() { - return refCount.decrementAndGet(); - } - - public int getRefCount() { - return refCount.get(); - } - - public MemoryWebsocketStore getMemoryStore() { - return memoryStore; - } - - public WebsocketComponentServlet getServlet() { - return servlet; - } - - public ServerConnector getConnector() { - return connector; - } - } - - public WebsocketComponent() { - this.setUseGlobalSslContextParameters(true); - // this will automatically set up the ids handler factory - this.setSocketFactories(new HashMap<>()); - } - - /** Connects the URL specified on the endpoint to the specified processor. */ - public void connect(WebsocketProducerConsumer prodcon) throws Exception { - WebsocketEndpoint endpoint = prodcon.getEndpoint(); - - String connectorKey = getConnectorKey(endpoint); - - synchronized (CONNECTORS) { - ConnectorRef connectorRef = CONNECTORS.get(connectorKey); - if (connectorRef == null) { - // Create Server and add connector - Server server = createServer(); - - ServerConnector connector = getSocketConnector(server, endpoint.getSslContextParameters()); - - if (endpoint.getPort() != null) { - connector.setPort(endpoint.getPort()); - } else { - connector.setPort(port); - } - - if (endpoint.getHost() != null) { - connector.setHost(endpoint.getHost()); - } else { - connector.setHost(host); - } - - server.addConnector(connector); - - LOG.trace("Jetty Connector added: {}", connector.getName()); - - // Create ServletContextHandler - ServletContextHandler context = createContext(server, connector, endpoint.getHandlers()); - // setup the WebSocketComponentServlet initial parameters - setWebSocketComponentServletInitialParameter(context, endpoint); - server.setHandler(context); - - // Apply CORS (http://www.w3.org/TR/cors/) - applyCrossOriginFiltering(endpoint, context); - - MemoryWebsocketStore memoryStore = new MemoryWebsocketStore(); - - // Don't provide a Servlet object as Producer/Consumer will create them later on - connectorRef = new ConnectorRef(server, connector, null, memoryStore); - - // must enable session before we start - if (endpoint.isSessionSupport()) { - enableSessionSupport(connectorRef.server, connectorKey); - } - LOG.info("Jetty Server starting on host: {}:{}", connector.getHost(), connector.getPort()); - connectorRef.memoryStore.start(); - connectorRef.server.start(); - - CONNECTORS.put(connectorKey, connectorRef); - - } else { - connectorRef.increment(); - } - - // check the session support - if (endpoint.isSessionSupport()) { - enableSessionSupport(connectorRef.server, connectorKey); - } - - NodeSynchronization sync = new DefaultNodeSynchronization(connectorRef.memoryStore); - WebsocketComponentServlet servlet = addServlet(sync, prodcon, endpoint.getResourceUri()); - if (prodcon instanceof WebsocketConsumer) { - WebsocketConsumer consumer = (WebsocketConsumer) prodcon; - if (servlet.getConsumer() == null) { - servlet.setConsumer(consumer); - } - // register the consumer here - servlet.connect(consumer); - } - if (prodcon instanceof WebsocketProducer) { - WebsocketProducer producer = (WebsocketProducer) prodcon; - producer.setStore(connectorRef.memoryStore); - } - } - } - - /** Disconnects the URL specified on the endpoint from the specified processor. */ - public void disconnect(WebsocketProducerConsumer prodcon) throws Exception { - // If the connector is not needed anymore then stop it - WebsocketEndpoint endpoint = prodcon.getEndpoint(); - String connectorKey = getConnectorKey(endpoint); - - synchronized (CONNECTORS) { - ConnectorRef connectorRef = CONNECTORS.get(connectorKey); - if (connectorRef != null) { - if (connectorRef.decrement() == 0) { - LOG.info( - "Stopping Jetty Server as the last connector is disconnecting: {}: {}", - connectorRef.connector.getHost(), - connectorRef.connector.getPort()); - servlets.remove(createPathSpec(endpoint.getResourceUri())); - connectorRef.server.removeConnector(connectorRef.connector); - if (connectorRef.connector != null) { - // static server may not have set a connector - connectorRef.connector.stop(); - } - connectorRef.server.stop(); - connectorRef.memoryStore.stop(); - CONNECTORS.remove(connectorKey); - // Camel controls the lifecycle of these entities so remove the - // registered MBeans when Camel is done with the managed objects. - } - if (prodcon instanceof WebsocketConsumer) { - connectorRef.servlet.disconnect((WebsocketConsumer) prodcon); - } - if (prodcon instanceof WebsocketProducer) { - ((WebsocketProducer) prodcon).setStore(null); - } - } - } - } - - @Override - protected Endpoint createEndpoint(String uri, String remaining, Map parameters) - throws Exception { - SSLContextParameters sslContextParameters = - resolveAndRemoveReferenceParameter( - parameters, "sslContextParameters", SSLContextParameters.class); - - int port = extractPortNumber(remaining); - String host = extractHostName(remaining); - - WebsocketEndpoint endpoint = new WebsocketEndpoint(this, uri, remaining, parameters); - - // prefer to use endpoint configured over component configured - if (sslContextParameters == null) { - // fallback to component configured - sslContextParameters = getSslContextParameters(); - } - if (sslContextParameters == null) { - sslContextParameters = retrieveGlobalSslContextParameters(); - } - - endpoint.setSslContextParameters(sslContextParameters); - endpoint.setPort(port); - endpoint.setHost(host); - - setProperties(endpoint, parameters); - return endpoint; - } - - protected void setWebSocketComponentServletInitialParameter( - ServletContextHandler context, WebsocketEndpoint endpoint) { - if (endpoint.getBufferSize() != null) { - context.setInitParameter("bufferSize", endpoint.getBufferSize().toString()); - } - if (endpoint.getMaxIdleTime() != null) { - context.setInitParameter("maxIdleTime", endpoint.getMaxIdleTime().toString()); - } - if (endpoint.getMaxTextMessageSize() != null) { - context.setInitParameter("maxTextMessageSize", endpoint.getMaxTextMessageSize().toString()); - } - if (endpoint.getMaxBinaryMessageSize() != null) { - context.setInitParameter( - "maxBinaryMessageSize", endpoint.getMaxBinaryMessageSize().toString()); - } - if (endpoint.getMinVersion() != null) { - context.setInitParameter("minVersion", endpoint.getMinVersion().toString()); - } - } - - protected Server createServer() { - Server server = null; - if (minThreads == null && maxThreads == null && getThreadPool() == null) { - minThreads = 1; - // 1+selectors+acceptors - maxThreads = 2 * (1 + Runtime.getRuntime().availableProcessors() * 2); - } - // configure thread pool if min/max given - if (minThreads != null || maxThreads != null) { - if (getThreadPool() != null) { - throw new IllegalArgumentException( - "You cannot configure both minThreads/maxThreads " - + "and a custom threadPool on JettyHttpComponent: " - + this); - } - QueuedThreadPool qtp = new QueuedThreadPool(); - if (minThreads != null) { - qtp.setMinThreads(minThreads); - } - if (maxThreads != null) { - qtp.setMaxThreads(maxThreads); - } - // let the thread names indicate they are from the server - qtp.setName("CamelJettyWebSocketServer"); - try { - qtp.start(); - } catch (Exception e) { - throw new RuntimeCamelException( - "Error starting JettyWebSocketServer thread pool: " + qtp, e); - } - server = new Server(qtp); - ContextHandlerCollection collection = new ContextHandlerCollection(); - server.setHandler(collection); - } - - if (getThreadPool() != null) { - server = new Server(getThreadPool()); - ContextHandlerCollection collection = new ContextHandlerCollection(); - server.setHandler(collection); - } - - return server; - } - - protected Server createStaticResourcesServer( - Server server, ServletContextHandler context, String home) throws Exception { - - context.setContextPath("/"); - - SessionHandler sh = new SessionHandler(); - context.setSessionHandler(sh); - - if (home != null) { - String[] resources = home.split(":"); - if (LOG.isDebugEnabled()) { - LOG.debug(">>> Protocol found: {}, and resource: {}", resources[0], resources[1]); - } - - if (resources[0].equals("classpath")) { - context.setBaseResource( - new JettyClassPathResource(getCamelContext().getClassResolver(), resources[1])); - } else if (resources[0].equals("file")) { - context.setBaseResource(Resource.newResource(resources[1])); - } - DefaultServlet defaultServlet = new DefaultServlet(); - ServletHolder holder = new ServletHolder(defaultServlet); - - // avoid file locking on windows - // http://stackoverflow.com/questions/184312/how-to-make-jetty-dynamically-load-static-pages - holder.setInitParameter("useFileMappedBuffer", "false"); - context.addServlet(holder, "/"); - } - - server.setHandler(context); - - return server; - } - - protected Server createStaticResourcesServer( - ServletContextHandler context, String host, int port, String home) throws Exception { - Server server = new Server(); - HttpConfiguration httpConfig = new HttpConfiguration(); - ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConfig)); - connector.setHost(host); - connector.setPort(port); - server.addConnector(connector); - return createStaticResourcesServer(server, context, home); - } - - protected WebsocketComponentServlet addServlet( - NodeSynchronization sync, WebsocketProducerConsumer prodcon, String resourceUri) - throws Exception { - - // Get Connector from one of the Jetty Instances to add WebSocket Servlet - WebsocketEndpoint endpoint = prodcon.getEndpoint(); - String key = getConnectorKey(endpoint); - ConnectorRef connectorRef = getConnectors().get(key); - - WebsocketComponentServlet servlet; - - if (connectorRef != null) { - String pathSpec = createPathSpec(resourceUri); - servlet = servlets.get(pathSpec); - if (servlet == null) { - // Retrieve Context - ServletContextHandler context = (ServletContextHandler) connectorRef.server.getHandler(); - servlet = createServlet(sync, pathSpec, servlets, context); - connectorRef.servlet = servlet; - LOG.debug( - "WebSocket servlet added for the following path: {}, to the Jetty Server: {}", - pathSpec, - key); - } - - return servlet; - } else { - throw new Exception("Jetty instance has not been retrieved for : " + key); - } - } - - protected WebsocketComponentServlet createServlet( - NodeSynchronization sync, - String pathSpec, - Map servlets, - ServletContextHandler handler) { - WebsocketComponentServlet servlet = - new WebsocketComponentServlet(sync, pathSpec, getSocketFactories()); - servlets.put(pathSpec, servlet); - ServletHolder servletHolder = new ServletHolder(servlet); - servletHolder.getInitParameters().putAll(handler.getInitParams()); - // Jetty 9 parameter bufferSize is now inputBufferSize - servletHolder.setInitParameter("inputBufferSize", handler.getInitParameter("bufferSize")); - handler.addServlet(servletHolder, pathSpec); - return servlet; - } - - protected ServletContextHandler createContext( - Server server, Connector connector, List handlers) { - ServletContextHandler context = - new ServletContextHandler( - server, "/", ServletContextHandler.NO_SECURITY | ServletContextHandler.NO_SESSIONS); - server.addConnector(connector); - - if (handlers != null && !handlers.isEmpty()) { - for (Handler handler : handlers) { - if (handler instanceof HandlerWrapper) { - ((HandlerWrapper) handler).setHandler(server.getHandler()); - server.setHandler(handler); - } else { - HandlerCollection handlerCollection = new HandlerCollection(); - handlerCollection.addHandler(server.getHandler()); - handlerCollection.addHandler(handler); - server.setHandler(handlerCollection); - } - } - } - - return context; - } - - private void enableSessionSupport(Server server, String connectorKey) { - ServletContextHandler context = server.getChildHandlerByClass(ServletContextHandler.class); - if (context.getSessionHandler() == null) { - SessionHandler sessionHandler = new SessionHandler(); - if (context.isStarted()) { - throw new IllegalStateException( - "Server has already been started. " - + "Cannot enabled sessionSupport on " - + connectorKey); - } else { - context.setSessionHandler(sessionHandler); - } - } - } - - private ServerConnector getSocketConnector( - Server server, SSLContextParameters sslContextParameters) - throws GeneralSecurityException, IOException { - if (sslContextParameters == null) { - sslContextParameters = retrieveGlobalSslContextParameters(); - } - if (sslContextParameters != null) { - try { - ProxyX509TrustManager.bindCertificatePair(sslContextParameters, true, certificatePair); - } catch (GeneralSecurityException | IOException e) { - LOG.error("Failed to patch TrustManager for WebsocketComponent", e); - } - SslContextFactory sslContextFactory = new SslContextFactory.Server(); - sslContextFactory.setSslContext(sslContextParameters.createSSLContext(getCamelContext())); - return new ServerConnector(server, sslContextFactory); - } else { - return new ServerConnector(server); - } - } - - public static String createPathSpec(String remaining) { - int index = remaining.indexOf('/'); - if (index != -1) { - return remaining.substring(index); - } else { - return "/" + remaining; - } - } - - private int extractPortNumber(String remaining) { - int index1 = remaining.indexOf(':'); - int index2 = remaining.indexOf('/'); - - if ((index1 != -1) && (index2 != -1)) { - String result = remaining.substring(index1 + 1, index2); - return Integer.parseInt(result); - } else { - return port; - } - } - - private String extractHostName(String remaining) { - int index = remaining.indexOf(':'); - if (index != -1) { - return remaining.substring(0, index); - } else { - return host; - } - } - - private static String getConnectorKey(WebsocketEndpoint endpoint) { - return endpoint.getProtocol() + ":" + endpoint.getHost() + ":" + endpoint.getPort(); - } - - private void applyCrossOriginFiltering( - WebsocketEndpoint endpoint, ServletContextHandler context) { - if (endpoint.isCrossOriginFilterOn()) { - FilterHolder filterHolder = new FilterHolder(); - CrossOriginFilter filter = new CrossOriginFilter(); - filterHolder.setFilter(filter); - filterHolder.setInitParameter("allowedOrigins", endpoint.getAllowedOrigins()); - context.addFilter( - filterHolder, endpoint.getFilterPath(), EnumSet.allOf(DispatcherType.class)); - } - } - - // Properties - // ------------------------------------------------------------------------- - - public String getStaticResources() { - return staticResources; - } - - /** - * Set a resource path for static resources (such as .html files etc). - * - *

The resources can be loaded from classpath, if you prefix with classpath:, - * otherwise the resources is loaded from file system or from JAR files. - * - *

For example to load from root classpath use classpath:., or - * classpath:WEB-INF/static - * - *

If not configured (eg null) then no static resource is in use. - */ - public void setStaticResources(String staticResources) { - this.staticResources = staticResources; - } - - public String getHost() { - return host; - } - - /** The hostname. The default value is 0.0.0.0 */ - public void setHost(String host) { - this.host = host; - } - - public Integer getPort() { - return port; - } - - /** The port number. The default value is 9292 */ - public void setPort(Integer port) { - this.port = port; - } - - public String getSslKeyPassword() { - return sslKeyPassword; - } - - public String getSslPassword() { - return sslPassword; - } - - public String getSslKeystore() { - return sslKeystore; - } - - /** The password for the keystore when using SSL. */ - public void setSslKeyPassword(String sslKeyPassword) { - this.sslKeyPassword = sslKeyPassword; - } - - /** The password when using SSL. */ - public void setSslPassword(String sslPassword) { - this.sslPassword = sslPassword; - } - - /** The path to the keystore. */ - public void setSslKeystore(String sslKeystore) { - this.sslKeystore = sslKeystore; - } - - public Integer getMinThreads() { - return minThreads; - } - - /** - * To set a value for minimum number of threads in server thread pool. MaxThreads/minThreads or - * threadPool fields are required due to switch to Jetty9. The default values for minThreads is 1. - */ - public void setMinThreads(Integer minThreads) { - this.minThreads = minThreads; - } - - public Integer getMaxThreads() { - return maxThreads; - } - - /** - * To set a value for maximum number of threads in server thread pool. MaxThreads/minThreads or - * threadPool fields are required due to switch to Jetty9. The default values for maxThreads is 1 - * + 2 * noCores. - */ - public void setMaxThreads(Integer maxThreads) { - this.maxThreads = maxThreads; - } - - public ThreadPool getThreadPool() { - return threadPool; - } - - /** - * To use a custom thread pool for the server. MaxThreads/minThreads or threadPool fields are - * required due to switch to Jetty9. - */ - public void setThreadPool(ThreadPool threadPool) { - this.threadPool = threadPool; - } - - public SSLContextParameters getSslContextParameters() { - return sslContextParameters; - } - - /** To configure security using SSLContextParameters */ - public void setSslContextParameters(SSLContextParameters sslContextParameters) { - this.sslContextParameters = sslContextParameters; - } - - @Override - public boolean isUseGlobalSslContextParameters() { - return this.useGlobalSslContextParameters; - } - - /** Enable usage of global SSL context parameters. */ - @Override - public void setUseGlobalSslContextParameters(boolean useGlobalSslContextParameters) { - this.useGlobalSslContextParameters = useGlobalSslContextParameters; - } - - public Map getSocketFactories() { - return socketFactories; - } - - /** - * To configure a map which contains custom WebSocketFactory for sub protocols. The key in the map - * is the sub protocol. - * - *

The default key is reserved for the default implementation. - */ - public void setSocketFactories(Map socketFactories) { - this.socketFactories = socketFactories; - - if (!this.socketFactories.containsKey("ids")) { - this.socketFactories.put("ids", new DefaultWebsocketFactory(certificatePair)); - } - } - - public static Map getConnectors() { - return CONNECTORS; - } - - @Override - protected void doStart() throws Exception { - super.doStart(); - } - - @Override - public void doStop() throws Exception { - super.doStop(); - if (CONNECTORS.size() > 0) { - for (ConnectorRef connectorRef : CONNECTORS.values()) { - if (connectorRef != null && connectorRef.getRefCount() == 0) { - connectorRef.server.removeConnector(connectorRef.connector); - connectorRef.connector.stop(); - connectorRef.server.stop(); - connectorRef.memoryStore.stop(); - connectorRef.servlet = null; - } - } - } - CONNECTORS.clear(); - - servlets.clear(); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketComponentServlet.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketComponentServlet.java deleted file mode 100644 index 9b1486d34..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketComponentServlet.java +++ /dev/null @@ -1,82 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import org.eclipse.jetty.websocket.servlet.WebSocketServlet; -import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class WebsocketComponentServlet extends WebSocketServlet { - private static final long serialVersionUID = 1L; - private static final Logger LOG = LoggerFactory.getLogger(WebsocketComponentServlet.class); - - private final NodeSynchronization sync; - private final Map socketFactories; - private final String pathSpec; - - private WebsocketConsumer consumer; - private static final ConcurrentMap consumers = - new ConcurrentHashMap<>(); - - public WebsocketComponentServlet( - NodeSynchronization sync, String pathSpec, Map socketFactories) { - this.sync = sync; - this.socketFactories = socketFactories; - this.pathSpec = pathSpec; - } - - public WebsocketConsumer getConsumer() { - return consumer; - } - - public void setConsumer(WebsocketConsumer consumer) { - this.consumer = consumer; - } - - public void connect(WebsocketConsumer consumer) { - LOG.debug("Connecting consumer: {}", consumer); - consumers.put(consumer.getPath(), consumer); - } - - public void disconnect(WebsocketConsumer consumer) { - LOG.debug("Disconnecting consumer: {}", consumer); - consumers.remove(consumer.getPath()); - } - - @Override - public void configure(WebSocketServletFactory factory) { - factory.setCreator( - (req, resp) -> { - String protocolKey = "ids"; - if (req.getSubProtocols().isEmpty() || req.getSubProtocols().contains(protocolKey)) { - WebSocketFactory wsFactory = socketFactories.get(protocolKey); - resp.setAcceptedSubProtocol(protocolKey); - return wsFactory.newInstance(req, protocolKey, pathSpec, sync, consumer); - } else { - LOG.error("WS subprotocols not supported: {}", String.join(",", req.getSubProtocols())); - return null; - } - }); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketConstants.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketConstants.java deleted file mode 100644 index 6c1b28f8d..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketConstants.java +++ /dev/null @@ -1,34 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -public final class WebsocketConstants { - - public static final int DEFAULT_PORT = 9292; - public static final String DEFAULT_HOST = "0.0.0.0"; - - public static final String CONNECTION_KEY = "websocket.connectionKey"; - public static final String SEND_TO_ALL = "websocket.sendToAll"; - - public static final String WS_PROTOCOL = "ws"; - public static final String WSS_PROTOCOL = "wss"; - - private WebsocketConstants() {} -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketConsumer.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketConsumer.java deleted file mode 100644 index 89d62610e..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketConsumer.java +++ /dev/null @@ -1,87 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import org.apache.camel.Exchange; -import org.apache.camel.Processor; -import org.apache.camel.support.DefaultConsumer; - -public class WebsocketConsumer extends DefaultConsumer implements WebsocketProducerConsumer { - - private final WebsocketEndpoint endpoint; - - public WebsocketConsumer(WebsocketEndpoint endpoint, Processor processor) { - super(endpoint, processor); - this.endpoint = endpoint; - } - - @Override - public void doStart() throws Exception { - super.doStart(); - endpoint.connect(this); - } - - @Override - public void doStop() throws Exception { - endpoint.disconnect(this); - super.doStop(); - } - - public WebsocketEndpoint getEndpoint() { - return endpoint; - } - - public String getPath() { - return endpoint.getPath(); - } - - public int getAttestationType() { - return endpoint.getAttestation(); - } - - public int getAttestationMask() { - return endpoint.getAttestationMask(); - } - - public void sendMessage(final String connectionKey, final String message) { - sendMessage(connectionKey, (Object) message); - } - - public void sendMessage(final String connectionKey, final Object message) { - - final Exchange exchange = getEndpoint().createExchange(); - - // set header and body - exchange.getIn().setHeader(WebsocketConstants.CONNECTION_KEY, connectionKey); - exchange.getIn().setBody(message); - - // send exchange using the async routing engine - getAsyncProcessor() - .process( - exchange, - doneSync -> { - if (exchange.getException() != null) { - getExceptionHandler() - .handleException( - "Error processing exchange", exchange, exchange.getException()); - } - }); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketEndpoint.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketEndpoint.java deleted file mode 100644 index ac46d7b3f..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketEndpoint.java +++ /dev/null @@ -1,360 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import org.apache.camel.Consumer; -import org.apache.camel.Processor; -import org.apache.camel.Producer; -import org.apache.camel.spi.Metadata; -import org.apache.camel.spi.UriEndpoint; -import org.apache.camel.spi.UriParam; -import org.apache.camel.spi.UriPath; -import org.apache.camel.support.DefaultEndpoint; -import org.apache.camel.support.jsse.SSLContextParameters; -import org.apache.camel.util.ObjectHelper; -import org.eclipse.jetty.server.Handler; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.List; -import java.util.Map; - -/** - * The websocket component provides websocket endpoints for communicating with clients using - * websocket. - * - *

This component uses Jetty as the websocket implementation. - */ -@UriEndpoint( - scheme = "idsserver", - title = "IDS Server Socket", - syntax = "idsserver:host:port/resourceUri", - consumerClass = WebsocketConsumer.class, - label = "idsserver" -) -public class WebsocketEndpoint extends DefaultEndpoint { - - private WebsocketComponent component; - private URI uri; - private List handlers; - - @UriPath(defaultValue = "0.0.0.0") - private String host; - - @UriPath(defaultValue = "9292") - private Integer port; - - @UriPath - @Metadata(required = true) - private String resourceUri; - - @UriParam(label = "producer", defaultValue = "30000") - private Integer sendTimeout = 30000; - - @UriParam(label = "consumer") - private boolean sessionSupport; - - @UriParam(label = "cors", description = "enables or disables Cross Origin Filter") - private boolean crossOriginFilterOn; - - @UriParam( - label = "sslContextParameters", - description = "used to save the SSLContextParameters when connecting via idsclient:// " - ) - private SSLContextParameters sslContextParameters; - - @UriParam(label = "cors") - private String allowedOrigins; - - @UriParam(label = "cors") - private String filterPath; - - @UriParam(label = "advanced", defaultValue = "8192") - private Integer bufferSize; - - @UriParam(label = "advanced", defaultValue = "300000") - private Integer maxIdleTime; - - @UriParam(label = "advanced") - private Integer maxTextMessageSize; - - @UriParam(defaultValue = "-1") - private Integer maxBinaryMessageSize; - - @UriParam(label = "advanced", defaultValue = "13") - private Integer minVersion; - - @UriParam( - label = "attestation", - defaultValue = "0", - description = - "defines the remote attestation mode: 0=BASIC, 1=ALL, 2=ADVANCED, 3=ZERO. default value is 0=BASIC. (see api/attestation.proto for more details)" - ) - private Integer attestation = 0; - - @UriParam( - label = "attestationMask", - defaultValue = "0", - description = - "defines the upper boundary of PCR values tested in ADVANCED mode. i.e. attestationMask=5 means values PCR0, PCR1, PCR2, PCR3 and PCR4" - ) - private Integer attestationMask = 0; - - public WebsocketEndpoint( - WebsocketComponent component, - String uri, - String resourceUri, - Map parameters) { - super(uri, component); - this.resourceUri = resourceUri; - this.component = component; - try { - this.uri = new URI(uri); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - } - - @Override - public WebsocketComponent getComponent() { - ObjectHelper.notNull(component, "component"); - return (WebsocketComponent) super.getComponent(); - } - - @Override - public Consumer createConsumer(Processor processor) throws Exception { - ObjectHelper.notNull(component, "component"); - WebsocketConsumer consumer = new WebsocketConsumer(this, processor); - configureConsumer(consumer); - return consumer; - } - - @Override - public Producer createProducer() { - return new WebsocketProducer(this); - } - - public void connect(WebsocketConsumer consumer) throws Exception { - component.connect(consumer); - } - - public void disconnect(WebsocketConsumer consumer) throws Exception { - component.disconnect(consumer); - } - - public void connect(WebsocketProducer producer) throws Exception { - component.connect(producer); - } - - public void disconnect(WebsocketProducer producer) throws Exception { - component.disconnect(producer); - } - - @Override - public boolean isSingleton() { - return true; - } - - public URI getUri() { - return uri; - } - - public Integer getPort() { - return port; - } - - public String getHost() { - return host; - } - - /** - * The hostname. The default value is 0.0.0.0. Setting this option on the component will - * use the component configured value as default. - */ - public void setHost(String host) { - this.host = host; - } - - /** - * The port number. The default value is 9292. Setting this option on the component will - * use the component configured value as default. - */ - public void setPort(int port) { - this.port = port; - } - - public Integer getSendTimeout() { - return sendTimeout; - } - - /** - * Timeout in millis when sending to a websocket channel. The default timeout is 30000 (30 - * seconds). - */ - public void setSendTimeout(Integer sendTimeout) { - this.sendTimeout = sendTimeout; - } - - public String getProtocol() { - return uri.getScheme(); - } - - public String getPath() { - return uri.getPath(); - } - - /** Whether to enable session support which enables HttpSession for each http request. */ - public void setSessionSupport(boolean support) { - sessionSupport = support; - } - - public boolean isSessionSupport() { - return sessionSupport; - } - - public Integer getBufferSize() { - return bufferSize; - } - - public int getAttestation() { - return attestation; - } - - public void setAttestation(int i) { - attestation = i; - } - - public int getAttestationMask() { - return attestationMask; - } - - public void setAttestationMask(int i) { - attestationMask = i; - } - - /** - * Set the buffer size of the websocketServlet, which is also the max frame byte size (default - * 8192) - */ - public void setBufferSize(Integer bufferSize) { - this.bufferSize = bufferSize; - } - - public Integer getMaxIdleTime() { - return maxIdleTime; - } - - /** - * Set the time in ms that the websocket created by the websocketServlet may be idle before - * closing. (default is 300000) - */ - public void setMaxIdleTime(Integer maxIdleTime) { - this.maxIdleTime = maxIdleTime; - } - - public Integer getMaxTextMessageSize() { - return maxTextMessageSize; - } - - /** - * Can be used to set the size in characters that the websocket created by the websocketServlet - * may be accept before closing. - */ - public void setMaxTextMessageSize(Integer maxTextMessageSize) { - this.maxTextMessageSize = maxTextMessageSize; - } - - public Integer getMaxBinaryMessageSize() { - return maxBinaryMessageSize; - } - - /** - * Can be used to set the size in bytes that the websocket created by the websocketServlet may be - * accept before closing. (Default is -1 - or unlimited) - */ - public void setMaxBinaryMessageSize(Integer maxBinaryMessageSize) { - this.maxBinaryMessageSize = maxBinaryMessageSize; - } - - public Integer getMinVersion() { - return minVersion; - } - - /** - * Can be used to set the minimum protocol version accepted for the websocketServlet. (Default 13 - * - the RFC6455 version) - */ - public void setMinVersion(Integer minVersion) { - this.minVersion = minVersion; - } - - public List getHandlers() { - return handlers; - } - - public void setHandlers(List handlers) { - this.handlers = handlers; - } - - public SSLContextParameters getSslContextParameters() { - return sslContextParameters; - } - - /** To configure security using SSLContextParameters */ - public void setSslContextParameters(SSLContextParameters sslContextParameters) { - this.sslContextParameters = sslContextParameters; - } - - public String getAllowedOrigins() { - return allowedOrigins; - } - - /** The CORS allowed origins. Use * to allow all. */ - public void setAllowedOrigins(String allowedOrigins) { - this.allowedOrigins = allowedOrigins; - } - - public boolean isCrossOriginFilterOn() { - return crossOriginFilterOn; - } - - /** Whether to enable CORS */ - public void setCrossOriginFilterOn(boolean crossOriginFilterOn) { - this.crossOriginFilterOn = crossOriginFilterOn; - } - - public String getFilterPath() { - return filterPath; - } - - /** Context path for filtering CORS */ - public void setFilterPath(String filterPath) { - this.filterPath = filterPath; - } - - public String getResourceUri() { - return resourceUri; - } - - /** Name of the websocket channel to use */ - public void setResourceUri(String resourceUri) { - this.resourceUri = resourceUri; - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketProducer.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketProducer.java deleted file mode 100644 index 29aa0cb26..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketProducer.java +++ /dev/null @@ -1,119 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.apache.camel.support.DefaultProducer; -import org.asynchttpclient.netty.handler.StreamedResponsePublisher; - -import java.nio.ByteBuffer; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -public class WebsocketProducer extends DefaultProducer implements WebsocketProducerConsumer { - - private WebsocketStore store; - private final WebsocketEndpoint endpoint; - - public WebsocketProducer(WebsocketEndpoint endpoint) { - super(endpoint); - this.endpoint = endpoint; - } - - @Override - public void process(Exchange exchange) throws Exception { - Message in = exchange.getIn(); - Object message = in.getMandatoryBody(); - if (!(message == null || message instanceof String || message instanceof byte[])) { - message = in.getMandatoryBody(String.class); - } - - // look for connection key and get Websocket - String connectionKey = in.getHeader(WebsocketConstants.CONNECTION_KEY, String.class); - if (connectionKey != null) { - String pathSpec = ""; - if (endpoint.getResourceUri() != null) { - pathSpec = WebsocketComponent.createPathSpec(endpoint.getResourceUri()); - } - DefaultWebsocket websocket = store.get(connectionKey + pathSpec); - log.debug("Sending to connection key {} -> {}", connectionKey, message); - Future future = sendMessage(websocket, message); - StreamedResponsePublisher sp; - if (future != null) { - int timeout = endpoint.getSendTimeout(); - future.get(timeout, TimeUnit.MILLISECONDS); - if (!future.isCancelled() && !future.isDone()) { - throw new WebsocketSendException( - "Failed to send message to the connection within " + timeout + " millis.", exchange); - } - } - } else { - throw new WebsocketSendException( - "Failed to send message to single connection; connection key not set.", exchange); - } - } - - public WebsocketEndpoint getEndpoint() { - return endpoint; - } - - @Override - public void doStart() throws Exception { - super.doStart(); - endpoint.connect(this); - } - - @Override - public void doStop() throws Exception { - endpoint.disconnect(this); - super.doStop(); - } - - Future sendMessage(DefaultWebsocket websocket, Object message) { - Future future = null; - // in case there is web socket and socket connection is open - send message - if (websocket != null && websocket.getSession().isOpen()) { - log.trace("Sending to websocket {} -> {}", websocket.getConnectionKey(), message); - if (message instanceof String) { - future = websocket.getSession().getRemote().sendStringByFuture((String) message); - } else if (message instanceof byte[]) { - ByteBuffer buf = ByteBuffer.wrap((byte[]) message); - future = websocket.getSession().getRemote().sendBytesByFuture(buf); - } - } - return future; - } - - // Store is set/unset upon connect/disconnect of the producer - public void setStore(WebsocketStore store) { - this.store = store; - } - - /** Called when a sleep is interrupted; allows derived classes to handle this case differently */ - protected void handleSleepInterruptedException(InterruptedException e, Exchange exchange) - throws InterruptedException { - if (log.isDebugEnabled()) { - log.debug("Sleep interrupted, are we stopping? {}", isStopping() || isStopped()); - } - Thread.currentThread().interrupt(); - throw e; - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketSendException.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketSendException.java deleted file mode 100644 index 30755018e..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketSendException.java +++ /dev/null @@ -1,37 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import org.apache.camel.CamelExchangeException; -import org.apache.camel.Exchange; - -/** Exception while sending to a websocket channel. */ -public class WebsocketSendException extends CamelExchangeException { - - private static final long serialVersionUID = 1L; - - public WebsocketSendException(String message, Exchange exchange) { - super(message, exchange); - } - - public WebsocketSendException(String message, Exchange exchange, Throwable cause) { - super(message, exchange, cause); - } -} diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketStore.java b/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketStore.java deleted file mode 100644 index cfabafb28..000000000 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketStore.java +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.server; - -import java.util.Collection; -import org.apache.camel.Service; - -public interface WebsocketStore extends Service { - - void add(DefaultWebsocket ws); - - void remove(DefaultWebsocket ws); - - void remove(String key); - - DefaultWebsocket get(String key); - - Collection getAll(); -} diff --git a/camel-ids/src/main/resources/META-INF/services/org/apache/camel/component/idsclient b/camel-ids/src/main/resources/META-INF/services/org/apache/camel/component/idsclient deleted file mode 100644 index 688c0cadd..000000000 --- a/camel-ids/src/main/resources/META-INF/services/org/apache/camel/component/idsclient +++ /dev/null @@ -1,17 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -class=de.fhg.aisec.ids.camel.ids.client.WsComponent diff --git a/camel-ids/src/test/java/de/fhg/aisec/ids/camel/ids/IdsClientServerPlaintextWithAttestationTest.java b/camel-ids/src/test/java/de/fhg/aisec/ids/camel/ids/IdsClientServerPlaintextWithAttestationTest.java deleted file mode 100644 index eacfd8287..000000000 --- a/camel-ids/src/test/java/de/fhg/aisec/ids/camel/ids/IdsClientServerPlaintextWithAttestationTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-ids - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids; - -import de.fhg.aisec.ids.api.conm.IDSCPIncomingConnection; -import de.fhg.aisec.ids.api.conm.IDSCPOutgoingConnection; -import de.fhg.aisec.ids.api.conm.RatResult; -import de.fhg.aisec.ids.api.settings.ConnectionSettings; -import de.fhg.aisec.ids.api.settings.ConnectorConfig; -import de.fhg.aisec.ids.api.settings.Settings; -import de.fhg.aisec.ids.api.tokenm.TokenManager; -import de.fhg.aisec.ids.camel.ids.connectionmanagement.ConnectionManagerService; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.component.mock.MockEndpoint; -import org.apache.camel.test.junit4.CamelTestSupport; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; - -public class IdsClientServerPlaintextWithAttestationTest extends CamelTestSupport { - private static final String TEST_MESSAGE = "Hello World!"; - private static final String TEST_MESSAGE_2 = "Hello Again!"; - - @Before - public void mockRequiredBundles() throws Exception { - CamelComponent cc = new CamelComponent(); - Settings settings = mock(Settings.class); - ConnectorConfig connectorConfig = mock(ConnectorConfig.class); - when(settings.getConnectorConfig()).thenReturn(connectorConfig); - when(connectorConfig.getDapsUrl()).thenReturn("daps.mock.url"); - when(settings.getConnectionSettings(anyString())).thenReturn(new ConnectionSettings()); - cc.setSettings(settings); - TokenManager tm = mock(TokenManager.class); - when(tm.verifyJWT(anyString(), anyString(), anyString())).thenReturn(Collections.emptyMap()); - doNothing().when(tm).validateDATSecurityAttributes(any(), any(ConnectionSettings.class)); - cc.setTokenManager(tm); - CamelComponent.setInstance(cc); - } - - @Test - public void testFromRouteAToB() throws InterruptedException { - ConnectionManagerService conm = new ConnectionManagerService(); - assertTrue(conm.listIncomingConnections().isEmpty()); - - MockEndpoint mock = getMockEndpoint("mock:result"); - mock.expectedBodiesReceived(TEST_MESSAGE); - - // Send a test message into begin of client route - template.sendBody("direct:input", TEST_MESSAGE); - - // We expect that mock endpoint is happy and has received a message - mock.assertIsSatisfied(); - - // We expect one incoming connection to be listed by ConnectionManager - List incomings = conm.listIncomingConnections(); - assertEquals( - "Incoming connection established, but ConnectionManager did not list it.", - 1, - incomings.size()); - - IDSCPIncomingConnection incomingConnection = incomings.get(0); - - // We expect attestation to FAIL because unit tests have no valid TPM - RatResult ratResult = incomingConnection.getAttestationResult(); - assertEquals(RatResult.Status.FAILED, ratResult.getStatus()); - - // We expect some meta data about the remote endpoint - assertEquals("{\"message\":\"Infomodel is not available\"}", incomingConnection.getMetaData()); - - List outgoings = conm.listOutgoingConnections(); - assertEquals(1, outgoings.size()); - - // Also outgoing connection will have failed remote attestation - IDSCPOutgoingConnection outgoingConnection = outgoings.get(0); - assertEquals(RatResult.Status.FAILED, outgoingConnection.getAttestationResult().getStatus()); - - // ... and some meta data - String meta = outgoingConnection.getMetaData(); - assertEquals("{\"message\":\"Infomodel is not available\"}", meta); - } - - @Test - public void testTwoRoutesRestartConsumer() throws Exception { - MockEndpoint mock = getMockEndpoint("mock:result"); - - resetMocks(); - mock.expectedBodiesReceived(TEST_MESSAGE); - template.sendBody("direct:input", TEST_MESSAGE); - mock.assertIsSatisfied(); - - // Now stop and start the client route - log.info("Restarting client route"); - var routeController = context.getRouteController(); - routeController.stopRoute("client"); - routeController.startRoute("client"); - - resetMocks(); - mock.expectedBodiesReceived(TEST_MESSAGE_2); - template.sendBody("direct:input", TEST_MESSAGE_2); - mock.assertIsSatisfied(); - } - - @Override - protected RouteBuilder[] createRouteBuilders() { - return new RouteBuilder[] { - new RouteBuilder() { - public void configure() { - from("direct:input").routeId("client").to("idsclientplain://localhost:9292/zero"); - } - }, - new RouteBuilder() { - public void configure() { - from("idsserver://0.0.0.0:9292/zero").routeId("server").to("mock:result"); - } - } - }; - } -} diff --git a/camel-ids/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/camel-ids/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker deleted file mode 100644 index ca6ee9cea..000000000 --- a/camel-ids/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker +++ /dev/null @@ -1 +0,0 @@ -mock-maker-inline \ No newline at end of file diff --git a/camel-ids/ssl/ca.sh b/camel-ids/ssl/ca.sh deleted file mode 100755 index 0abca82ed..000000000 --- a/camel-ids/ssl/ca.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash -# - -cleanup(){ -echo "Cleanup unnecessary files" -[[ -f ${SUBCA_CSR} ]] && rm ${SUBCA_CSR} -[[ -f ${INDEX_FILE}.attr ]] && rm ${INDEX_FILE}.attr -[[ -f ${INDEX_FILE}.old ]] && rm ${INDEX_FILE}.old -[[ -f ${SERIAL_FILE}.old ]] && rm ${SERIAL_FILE}.old -[[ -f ${PEM_FILE} ]] && rm ${PEM_FILE} -} - -error_check(){ -if [ "$1" != "0" ]; then - echo "Error: $2" - cleanup - exit 1 -fi -} - -assert_file_exists(){ -if [ ! -f $1 ]; then - echo "Error: Missing file $1" - exit 1 -fi -} - -assert_file_not_exists(){ -if [ -f $1 ]; then - echo "Error: File $1 exists. Precautional exit" - exit 1 -fi -} - -CA_FOLDER="./ca" - -#root CA files -#root 01.pem -PEM_FILE="$CA_FOLDER/01.pem" -#root CA sign index file -INDEX_FILE="$CA_FOLDER/index.txt" -#root CA sign serial file -SERIAL_FILE="$CA_FOLDER/serial.txt" -#root CA config file -ROOTCA_CONFIG="configs/openssl-rootca.cnf" -#root CA cert file -ROOTCA_CERT="$CA_FOLDER/rootca.cert" -#root CA key file -ROOTCA_KEY="$CA_FOLDER/rootca.key" - -#sub CA config file -SUBCA_CONFIG="configs/openssl-subca.cnf" -#sub CA csr file -SUBCA_CSR="$CA_FOLDER/subca.csr" -#sub CA cert file -SUBCA_CERT="$CA_FOLDER/subca.cert" -#sub CA key file -SUBCA_KEY="$CA_FOLDER/subca.key" - -#ca chain file -CACHAIN_CERT="$CA_FOLDER/cachain.cert" - -if [ $# -eq 0 ] ; then - echo "No arguments supplied, which is good" -else - echo "Invalid number of arguments: $# (expected 0)" - echo "Usage: $0" - exit 1 -fi - -cd $(dirname $0) -echo "Check if directory is clean" -assert_file_not_exists ${INDEX_FILE} -assert_file_not_exists ${SERIAL_FILE} -assert_file_not_exists ${ROOTCA_CERT} -assert_file_not_exists ${ROOTCA_KEY} -assert_file_not_exists ${SUBCA_CERT} -assert_file_not_exists ${SUBCA_CSR} -assert_file_not_exists ${SUBCA_KEY} -assert_file_not_exists ${CACHAIN_CERT} - -echo "Trying to find required files" -assert_file_exists ${ROOTCA_CONFIG} -assert_file_exists ${SUBCA_CONFIG} -echo "Successfully found requrired files" - - -########## ROOT CA CERT ########## -# -nodes option omits passphrase -echo "Create self-signed root CA certificate" -openssl req -batch -x509 -config ${ROOTCA_CONFIG} -newkey rsa:2048 -sha1 -nodes -out ${ROOTCA_CERT} -outform PEM -days 7300 -keyout ${ROOTCA_KEY} -error_check $? "Failed to create self signed root CA certificate" - -########## SUB CA CERT ########## -# -nodes option omits passphrase -echo "Create sub CA CSR" -openssl req -batch -config ${SUBCA_CONFIG} -newkey rsa:2048 -sha1 -nodes -out ${SUBCA_CSR} -outform PEM -keyout ${SUBCA_KEY} -error_check $? "Failed to create sub CA CSR" - -echo "Sign sub CA CSR with root CA" -touch ca/index.txt -touch ca/serial.txt -echo '01' > ca/serial.txt -openssl ca -batch -config ${ROOTCA_CONFIG} -policy signing_policy -extensions signing_req_CA -out ${SUBCA_CERT} -infiles ${SUBCA_CSR} -error_check $? "Failed to sign sub CA CSR with root CA certificate" - -echo "Verify newly created sub CA certificate" -openssl verify -CAfile ${ROOTCA_CERT} ${SUBCA_CERT} -error_check $? "Failed to verify newly signed sub CA certificate" - -echo "Concatenate root CA to sub CA" -echo "************************** ROOT CA CERTIFICATE *****************************************" -cat ${ROOTCA_CERT} -echo "************************** SUB CA CERTIFICATE *****************************************" -cat ${SUBCA_CERT} - -cat ${ROOTCA_CERT} ${SUBCA_CERT} >> ${CACHAIN_CERT} - -echo "Cleanup temp files" -cleanup - -exit 0 diff --git a/camel-ids/ssl/ca/cachain.cert b/camel-ids/ssl/ca/cachain.cert deleted file mode 100644 index e55463562..000000000 --- a/camel-ids/ssl/ca/cachain.cert +++ /dev/null @@ -1,111 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDXTCCAkWgAwIBAgIJAPbCZBTm8zbBMA0GCSqGSIb3DQEBBQUAMD0xCzAJBgNV -BAYTAkRFMRMwEQYDVQQKDApGcmF1bmhvZmVyMRkwFwYDVQQDDBBJRFMgUm9vdCBD -QSAyMDE2MB4XDTE3MDIxNTEwMzkyMFoXDTM3MDIxMDEwMzkyMFowPTELMAkGA1UE -BhMCREUxEzARBgNVBAoMCkZyYXVuaG9mZXIxGTAXBgNVBAMMEElEUyBSb290IENB -IDIwMTYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyG8fCjoH2X+tr -BFGscizg7ODNTZd0GoyVOX1xkNmkLa1vMeo+mDfO8sXLzcRSFuNRfQHIR9O8jR6V -A5WhIzGYYvhO2mDl5NVAtGzljrPB2xCCzGyFDf4QOz+WPrJWGJ5ThhnaUIwC+Tcb -EYZUQfm2aSqIzRi876qCtYdIdxHvo32+M8APStkuOeGBZvNpVQiG4Hy3mECPLFZm -XphgfD1mGVWMRHE3iHnqO1zG3fWDWZcTzWlHd9/VaY9ruYKWow2Zh80mTIsOPrM8 -p9dh8PrNewXSMa4sKalMuyZAgwKbhgpcqSqdAIgl6pRafdjQeXvpJ4++VF+sAhkC -jYJTl7FfAgMBAAGjYDBeMB0GA1UdDgQWBBSZuq591Lv1vJSCsDLaYY12omzY6zAf -BgNVHSMEGDAWgBSZuq591Lv1vJSCsDLaYY12omzY6zAPBgNVHRMBAf8EBTADAQH/ -MAsGA1UdDwQEAwIBRjANBgkqhkiG9w0BAQUFAAOCAQEApfE/TCbERGvbATl7KnDk -v0CdHVsDikg91sFI+PgmVoMlxorBSMbAuv9+FOhHsje/rOkiaZ7XyhWawGTXeA5p -S26Qev0BJNQPisCFIGY9Pwa6cfASjmAlByxORGjkGOsOYaUYrbbrwFXUDRdqqs0f -tACuI0szGMa0GUz6kga8xy+wQ9nU6WXprTYQmbM4TPFJjUBdg26lE/QDH/AeLh/m -TX7amieWM85fM7gyIXc4ZKEHDEfn74fSXL1DU+t/NJYGK6x93r85PnNWGiKLIoht -ZfN+3mTT4IwKPPE7E/l6EMUCfXkvAZ/mguYlOD0kfdYzHt0FVW3F865gtH08bMJg -kw== ------END CERTIFICATE----- -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 1 (0x1) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS Root CA 2016 - Validity - Not Before: Feb 15 10:39:21 2017 GMT - Not After : Feb 13 10:39:21 2025 GMT - Subject: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:b6:b8:53:48:45:6d:8d:68:03:2d:9a:07:ba:ce: - 8f:31:d6:d5:1f:79:fa:ec:e9:9f:99:03:c9:2d:4e: - e7:ea:18:bb:00:38:0c:6b:f3:31:aa:6a:d5:58:42: - 5e:a7:fa:19:58:b1:87:31:dc:8a:1e:ba:a4:9f:9b: - 56:7a:b4:46:b3:43:eb:47:2c:ea:f7:0f:33:ff:c8: - 8c:b0:da:05:8e:14:fc:6a:5b:7b:bd:09:f7:84:b2: - 7b:db:fb:e7:b1:7d:d2:a1:d0:0e:a6:ef:5b:37:af: - 0c:c1:b6:76:25:9b:42:93:e7:63:00:cf:e8:52:86: - 4d:ee:5f:a8:4d:57:1b:58:7c:77:05:49:cd:55:4f: - 23:20:eb:c2:c7:be:3d:e9:2a:8c:58:f1:52:45:be: - 20:40:b4:7b:d8:a9:c5:e8:88:d2:ab:a7:15:74:32: - 6a:81:7f:e9:00:81:69:8f:0d:3d:ad:01:48:35:1f: - 4a:dc:74:e5:3b:5b:f7:ca:99:54:b3:d4:ca:a9:55: - 70:b6:da:7a:69:ea:66:cf:23:16:3b:ea:53:2f:b1: - de:9f:97:2b:7c:a6:68:21:ae:58:37:89:ef:e4:4d: - ad:aa:97:50:c3:87:61:f2:48:33:fb:c0:4a:09:f4: - bc:13:a6:e6:9e:7e:4b:90:2c:82:69:6a:6c:54:fc: - a2:a9 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - X509v3 Authority Key Identifier: - keyid:99:BA:AE:7D:D4:BB:F5:BC:94:82:B0:32:DA:61:8D:76:A2:6C:D8:EB - - X509v3 Basic Constraints: critical - CA:TRUE - X509v3 Key Usage: - Digital Signature, Certificate Sign, CRL Sign - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - Signature Algorithm: sha256WithRSAEncryption - 37:d8:e0:90:e8:3d:fe:bc:0d:12:83:95:b4:9e:cb:3b:13:20: - f9:4d:a2:39:b3:cb:1f:44:2d:b5:77:13:a0:5a:3b:dd:00:75: - f5:a1:e7:48:e0:3a:8d:84:c3:0b:67:eb:ec:7e:d4:af:89:fb: - ed:2b:e1:35:7a:f3:c3:62:2c:83:34:8c:dd:a8:2d:2f:ed:90: - 75:a7:4c:89:27:48:fa:45:44:2b:63:ea:f2:45:23:18:8e:68: - 4b:ec:ad:fa:2c:13:f1:25:3e:0f:14:75:bb:39:0e:64:65:67: - 35:9f:7d:16:6d:7a:1e:79:c3:41:4f:bf:98:14:f8:d1:ac:4d: - 31:16:db:8e:c2:22:89:56:8f:e0:1b:c0:fc:95:aa:cb:7e:a8: - a0:9a:93:da:5f:cd:e9:1d:9a:58:d9:c8:31:8d:57:fb:5f:bd: - 7e:bc:13:e3:e0:c7:64:65:49:28:22:88:cf:3e:f4:60:fd:53: - 9c:0b:fc:02:bb:c8:08:6e:c7:0f:08:ef:6f:90:5b:8f:27:0c: - 8f:d0:09:16:8e:1b:f0:42:ca:df:49:05:08:d3:0d:d3:fc:fb: - 70:27:9e:d5:9b:98:50:6b:11:ff:ef:d8:78:13:04:2f:6d:9d: - 70:8f:f8:cb:07:86:3f:55:56:49:c7:4b:2d:17:ce:cf:92:63: - ba:4c:3c:ec ------BEGIN CERTIFICATE----- -MIID5DCCAsygAwIBAgIBATANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEZMBcGA1UEAwwQSURTIFJvb3QgQ0EgMjAxNjAe -Fw0xNzAyMTUxMDM5MjFaFw0yNTAyMTMxMDM5MjFaMDsxCzAJBgNVBAYTAkRFMRMw -EQYDVQQKDApGcmF1bmhvZmVyMRcwFQYDVQQDDA5JRFMgU3ViQ0EgMjAxNjCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALa4U0hFbY1oAy2aB7rOjzHW1R95 -+uzpn5kDyS1O5+oYuwA4DGvzMapq1VhCXqf6GVixhzHcih66pJ+bVnq0RrND60cs -6vcPM//IjLDaBY4U/Gpbe70J94Sye9v757F90qHQDqbvWzevDMG2diWbQpPnYwDP -6FKGTe5fqE1XG1h8dwVJzVVPIyDrwse+PekqjFjxUkW+IEC0e9ipxeiI0qunFXQy -aoF/6QCBaY8NPa0BSDUfStx05Ttb98qZVLPUyqlVcLbaemnqZs8jFjvqUy+x3p+X -K3ymaCGuWDeJ7+RNraqXUMOHYfJIM/vASgn0vBOm5p5+S5AsgmlqbFT8oqkCAwEA -AaOB8DCB7TAdBgNVHQ4EFgQUiYuC72su5EAtzlxs93guerB7GR0wHwYDVR0jBBgw -FoAUmbqufdS79byUgrAy2mGNdqJs2OswDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8E -BAMCAYYwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDANBgkqhkiG9w0BAQsFAAOCAQEAN9jgkOg9/rwNEoOVtJ7LOxMg+U2iObPL -H0QttXcToFo73QB19aHnSOA6jYTDC2fr7H7Ur4n77SvhNXrzw2IsgzSM3agtL+2Q -dadMiSdI+kVEK2Pq8kUjGI5oS+yt+iwT8SU+DxR1uzkOZGVnNZ99Fm16HnnDQU+/ -mBT40axNMRbbjsIiiVaP4BvA/JWqy36ooJqT2l/N6R2aWNnIMY1X+1+9frwT4+DH -ZGVJKCKIzz70YP1TnAv8ArvICG7HDwjvb5BbjycMj9AJFo4b8ELK30kFCNMN0/z7 -cCee1ZuYUGsR/+/YeBMEL22dcI/4yweGP1VWScdLLRfOz5Jjukw87A== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/ca/index.txt b/camel-ids/ssl/ca/index.txt deleted file mode 100644 index fc4d4ef1c..000000000 --- a/camel-ids/ssl/ca/index.txt +++ /dev/null @@ -1,11 +0,0 @@ -V 190215104012Z 01 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215104017Z 02 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215105339Z 03 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215105401Z 04 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215105409Z 05 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215114845Z 06 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215114851Z 07 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215122054Z 08 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215122104Z 09 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215123310Z 0A unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215123319Z 0B unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client diff --git a/camel-ids/ssl/ca/index.txt.attr b/camel-ids/ssl/ca/index.txt.attr deleted file mode 100644 index 3a7e39e6e..000000000 --- a/camel-ids/ssl/ca/index.txt.attr +++ /dev/null @@ -1 +0,0 @@ -unique_subject = no diff --git a/camel-ids/ssl/ca/index.txt.attr.old b/camel-ids/ssl/ca/index.txt.attr.old deleted file mode 100644 index 3a7e39e6e..000000000 --- a/camel-ids/ssl/ca/index.txt.attr.old +++ /dev/null @@ -1 +0,0 @@ -unique_subject = no diff --git a/camel-ids/ssl/ca/index.txt.old b/camel-ids/ssl/ca/index.txt.old deleted file mode 100644 index d28f57290..000000000 --- a/camel-ids/ssl/ca/index.txt.old +++ /dev/null @@ -1,10 +0,0 @@ -V 190215104012Z 01 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215104017Z 02 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215105339Z 03 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215105401Z 04 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215105409Z 05 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215114845Z 06 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215114851Z 07 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215122054Z 08 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215122104Z 09 unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client -V 190215123310Z 0A unknown /C=DE/ST=Bayern/L=Muenchen/O=Fraunhofer/OU=AISEC/CN=AISEC IDS Client diff --git a/camel-ids/ssl/ca/rootca.cert b/camel-ids/ssl/ca/rootca.cert deleted file mode 100644 index 3aa1c366d..000000000 --- a/camel-ids/ssl/ca/rootca.cert +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDXTCCAkWgAwIBAgIJAPbCZBTm8zbBMA0GCSqGSIb3DQEBBQUAMD0xCzAJBgNV -BAYTAkRFMRMwEQYDVQQKDApGcmF1bmhvZmVyMRkwFwYDVQQDDBBJRFMgUm9vdCBD -QSAyMDE2MB4XDTE3MDIxNTEwMzkyMFoXDTM3MDIxMDEwMzkyMFowPTELMAkGA1UE -BhMCREUxEzARBgNVBAoMCkZyYXVuaG9mZXIxGTAXBgNVBAMMEElEUyBSb290IENB -IDIwMTYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyG8fCjoH2X+tr -BFGscizg7ODNTZd0GoyVOX1xkNmkLa1vMeo+mDfO8sXLzcRSFuNRfQHIR9O8jR6V -A5WhIzGYYvhO2mDl5NVAtGzljrPB2xCCzGyFDf4QOz+WPrJWGJ5ThhnaUIwC+Tcb -EYZUQfm2aSqIzRi876qCtYdIdxHvo32+M8APStkuOeGBZvNpVQiG4Hy3mECPLFZm -XphgfD1mGVWMRHE3iHnqO1zG3fWDWZcTzWlHd9/VaY9ruYKWow2Zh80mTIsOPrM8 -p9dh8PrNewXSMa4sKalMuyZAgwKbhgpcqSqdAIgl6pRafdjQeXvpJ4++VF+sAhkC -jYJTl7FfAgMBAAGjYDBeMB0GA1UdDgQWBBSZuq591Lv1vJSCsDLaYY12omzY6zAf -BgNVHSMEGDAWgBSZuq591Lv1vJSCsDLaYY12omzY6zAPBgNVHRMBAf8EBTADAQH/ -MAsGA1UdDwQEAwIBRjANBgkqhkiG9w0BAQUFAAOCAQEApfE/TCbERGvbATl7KnDk -v0CdHVsDikg91sFI+PgmVoMlxorBSMbAuv9+FOhHsje/rOkiaZ7XyhWawGTXeA5p -S26Qev0BJNQPisCFIGY9Pwa6cfASjmAlByxORGjkGOsOYaUYrbbrwFXUDRdqqs0f -tACuI0szGMa0GUz6kga8xy+wQ9nU6WXprTYQmbM4TPFJjUBdg26lE/QDH/AeLh/m -TX7amieWM85fM7gyIXc4ZKEHDEfn74fSXL1DU+t/NJYGK6x93r85PnNWGiKLIoht -ZfN+3mTT4IwKPPE7E/l6EMUCfXkvAZ/mguYlOD0kfdYzHt0FVW3F865gtH08bMJg -kw== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/ca/rootca.key b/camel-ids/ssl/ca/rootca.key deleted file mode 100644 index e538f2d25..000000000 --- a/camel-ids/ssl/ca/rootca.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCyG8fCjoH2X+tr -BFGscizg7ODNTZd0GoyVOX1xkNmkLa1vMeo+mDfO8sXLzcRSFuNRfQHIR9O8jR6V -A5WhIzGYYvhO2mDl5NVAtGzljrPB2xCCzGyFDf4QOz+WPrJWGJ5ThhnaUIwC+Tcb -EYZUQfm2aSqIzRi876qCtYdIdxHvo32+M8APStkuOeGBZvNpVQiG4Hy3mECPLFZm -XphgfD1mGVWMRHE3iHnqO1zG3fWDWZcTzWlHd9/VaY9ruYKWow2Zh80mTIsOPrM8 -p9dh8PrNewXSMa4sKalMuyZAgwKbhgpcqSqdAIgl6pRafdjQeXvpJ4++VF+sAhkC -jYJTl7FfAgMBAAECggEAJxloIfLM3vwxnx2knFm4Nmxp8UfuTqOhZwTm3+5viNYq -M7XeeX1LCxhKibITPf4eSv5JTOFPvx2vsADIcUZbldtsLUtNaEpy8jBpk39fQNhJ -aJ1d2Vu4AXIwRFhhJ/thjm5q8H0sL17sVPnk5kxReFTf7IYxvxBR+z3EhAj3nAaH -Rwj22YhDLqglcaBOGvStK1JYJp5M2AH7qjzDpNFRgxPIdU88SCA5TH/EDGGUo1K7 -enuST0qELdLYztC7QqqmHkLeNpmM5wIQGQenJ3RqUmKjdshKCxrpGmLVaPZI3751 -wbEnec0fhjETAPbX1TlX/OjCt/+MtQjC2E+qHCl9eQKBgQDaI0U3FSsLvEoXgxGe -RIDHVBX5C3Bky61W30IHArbM6yYuTVzAJFykMLkgyMxMBObRoRjqlqD+0Clgluov -k230ZsMvDb39fI5Q83RH0bl8kjGVvdufYFhGOGWLMLjNuSA80zZrsuTTL1SnmpT3 -tum2JD+zR3Zlrlc39mh25qKEFQKBgQDRBdnFjmX3/dgDwaANwBWS2rhfv1RVt5hX -qCEbfVIFzJUsq9OcFuqvHe+fAzfPzkhfQRO/v1y700j/WHT3PhtNGsOvEBvl+gzt -hWcEbm8VxHpkL4eQOLeQgHf8rq0wD802NyKwMyQrxGDp2Tuo7GpduVyqpVb/aFnd -qlKpGZU4owKBgQDXN/1OP2BdD8S6NeLoGAZGo7uaH6Mgj6PSFiv65r6cp1TgUgu0 -tyuAA2Jj6jlGt39UTHFc4oitX4uzdLJRhk/x1oG0pwZQVtfDHrAXO+CZ+1NYvh01 -vcTaY0IsdkGfF4uq92i2EaaahhQr2OQpExq7TkBbDaLO55e96yteRGcLkQKBgQC5 -t88Uvz9Opxblz4ZccU053Ghxelh+iNAtIk+4UxMr3+izdkBgseP3kEu2J2/RjeGz -8OiROIA2yrZTWs8iVuZ/DcbMpy2CmzgdWqh7wXumBZsRpUF4HUzMcbkqpDFxQLj+ -8OI7WFVNJgFOBhwCLX0cpXP2k03HRXqDf7BOW1LArQKBgQCwvmbZMhkxMUIUjEgK -3zpKICbz9FEkEYH83L6jgBDhres9QBJu5n5JldOFDC1ga/MiHYE8xiB9jEQNslbY -ktGGiq9Jan7qytUxHnHrU0KsYuu86asHFy/iLPt/C9M1xLu6+zZgWfPWCL2WLSGN -tH7Lvo+0B0k6quxxCo7Ak2m/Jw== ------END PRIVATE KEY----- diff --git a/camel-ids/ssl/ca/serial.txt b/camel-ids/ssl/ca/serial.txt deleted file mode 100644 index d73cdef37..000000000 --- a/camel-ids/ssl/ca/serial.txt +++ /dev/null @@ -1 +0,0 @@ -0C diff --git a/camel-ids/ssl/ca/serial.txt.old b/camel-ids/ssl/ca/serial.txt.old deleted file mode 100644 index eb589e9da..000000000 --- a/camel-ids/ssl/ca/serial.txt.old +++ /dev/null @@ -1 +0,0 @@ -0B diff --git a/camel-ids/ssl/ca/subca.cert b/camel-ids/ssl/ca/subca.cert deleted file mode 100644 index 136817b3b..000000000 --- a/camel-ids/ssl/ca/subca.cert +++ /dev/null @@ -1,90 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 1 (0x1) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS Root CA 2016 - Validity - Not Before: Feb 15 10:39:21 2017 GMT - Not After : Feb 13 10:39:21 2025 GMT - Subject: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:b6:b8:53:48:45:6d:8d:68:03:2d:9a:07:ba:ce: - 8f:31:d6:d5:1f:79:fa:ec:e9:9f:99:03:c9:2d:4e: - e7:ea:18:bb:00:38:0c:6b:f3:31:aa:6a:d5:58:42: - 5e:a7:fa:19:58:b1:87:31:dc:8a:1e:ba:a4:9f:9b: - 56:7a:b4:46:b3:43:eb:47:2c:ea:f7:0f:33:ff:c8: - 8c:b0:da:05:8e:14:fc:6a:5b:7b:bd:09:f7:84:b2: - 7b:db:fb:e7:b1:7d:d2:a1:d0:0e:a6:ef:5b:37:af: - 0c:c1:b6:76:25:9b:42:93:e7:63:00:cf:e8:52:86: - 4d:ee:5f:a8:4d:57:1b:58:7c:77:05:49:cd:55:4f: - 23:20:eb:c2:c7:be:3d:e9:2a:8c:58:f1:52:45:be: - 20:40:b4:7b:d8:a9:c5:e8:88:d2:ab:a7:15:74:32: - 6a:81:7f:e9:00:81:69:8f:0d:3d:ad:01:48:35:1f: - 4a:dc:74:e5:3b:5b:f7:ca:99:54:b3:d4:ca:a9:55: - 70:b6:da:7a:69:ea:66:cf:23:16:3b:ea:53:2f:b1: - de:9f:97:2b:7c:a6:68:21:ae:58:37:89:ef:e4:4d: - ad:aa:97:50:c3:87:61:f2:48:33:fb:c0:4a:09:f4: - bc:13:a6:e6:9e:7e:4b:90:2c:82:69:6a:6c:54:fc: - a2:a9 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - X509v3 Authority Key Identifier: - keyid:99:BA:AE:7D:D4:BB:F5:BC:94:82:B0:32:DA:61:8D:76:A2:6C:D8:EB - - X509v3 Basic Constraints: critical - CA:TRUE - X509v3 Key Usage: - Digital Signature, Certificate Sign, CRL Sign - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - Signature Algorithm: sha256WithRSAEncryption - 37:d8:e0:90:e8:3d:fe:bc:0d:12:83:95:b4:9e:cb:3b:13:20: - f9:4d:a2:39:b3:cb:1f:44:2d:b5:77:13:a0:5a:3b:dd:00:75: - f5:a1:e7:48:e0:3a:8d:84:c3:0b:67:eb:ec:7e:d4:af:89:fb: - ed:2b:e1:35:7a:f3:c3:62:2c:83:34:8c:dd:a8:2d:2f:ed:90: - 75:a7:4c:89:27:48:fa:45:44:2b:63:ea:f2:45:23:18:8e:68: - 4b:ec:ad:fa:2c:13:f1:25:3e:0f:14:75:bb:39:0e:64:65:67: - 35:9f:7d:16:6d:7a:1e:79:c3:41:4f:bf:98:14:f8:d1:ac:4d: - 31:16:db:8e:c2:22:89:56:8f:e0:1b:c0:fc:95:aa:cb:7e:a8: - a0:9a:93:da:5f:cd:e9:1d:9a:58:d9:c8:31:8d:57:fb:5f:bd: - 7e:bc:13:e3:e0:c7:64:65:49:28:22:88:cf:3e:f4:60:fd:53: - 9c:0b:fc:02:bb:c8:08:6e:c7:0f:08:ef:6f:90:5b:8f:27:0c: - 8f:d0:09:16:8e:1b:f0:42:ca:df:49:05:08:d3:0d:d3:fc:fb: - 70:27:9e:d5:9b:98:50:6b:11:ff:ef:d8:78:13:04:2f:6d:9d: - 70:8f:f8:cb:07:86:3f:55:56:49:c7:4b:2d:17:ce:cf:92:63: - ba:4c:3c:ec ------BEGIN CERTIFICATE----- -MIID5DCCAsygAwIBAgIBATANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEZMBcGA1UEAwwQSURTIFJvb3QgQ0EgMjAxNjAe -Fw0xNzAyMTUxMDM5MjFaFw0yNTAyMTMxMDM5MjFaMDsxCzAJBgNVBAYTAkRFMRMw -EQYDVQQKDApGcmF1bmhvZmVyMRcwFQYDVQQDDA5JRFMgU3ViQ0EgMjAxNjCCASIw -DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALa4U0hFbY1oAy2aB7rOjzHW1R95 -+uzpn5kDyS1O5+oYuwA4DGvzMapq1VhCXqf6GVixhzHcih66pJ+bVnq0RrND60cs -6vcPM//IjLDaBY4U/Gpbe70J94Sye9v757F90qHQDqbvWzevDMG2diWbQpPnYwDP -6FKGTe5fqE1XG1h8dwVJzVVPIyDrwse+PekqjFjxUkW+IEC0e9ipxeiI0qunFXQy -aoF/6QCBaY8NPa0BSDUfStx05Ttb98qZVLPUyqlVcLbaemnqZs8jFjvqUy+x3p+X -K3ymaCGuWDeJ7+RNraqXUMOHYfJIM/vASgn0vBOm5p5+S5AsgmlqbFT8oqkCAwEA -AaOB8DCB7TAdBgNVHQ4EFgQUiYuC72su5EAtzlxs93guerB7GR0wHwYDVR0jBBgw -FoAUmbqufdS79byUgrAy2mGNdqJs2OswDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8E -BAMCAYYwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDANBgkqhkiG9w0BAQsFAAOCAQEAN9jgkOg9/rwNEoOVtJ7LOxMg+U2iObPL -H0QttXcToFo73QB19aHnSOA6jYTDC2fr7H7Ur4n77SvhNXrzw2IsgzSM3agtL+2Q -dadMiSdI+kVEK2Pq8kUjGI5oS+yt+iwT8SU+DxR1uzkOZGVnNZ99Fm16HnnDQU+/ -mBT40axNMRbbjsIiiVaP4BvA/JWqy36ooJqT2l/N6R2aWNnIMY1X+1+9frwT4+DH -ZGVJKCKIzz70YP1TnAv8ArvICG7HDwjvb5BbjycMj9AJFo4b8ELK30kFCNMN0/z7 -cCee1ZuYUGsR/+/YeBMEL22dcI/4yweGP1VWScdLLRfOz5Jjukw87A== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/ca/subca.key b/camel-ids/ssl/ca/subca.key deleted file mode 100644 index 3b4a125ac..000000000 --- a/camel-ids/ssl/ca/subca.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC2uFNIRW2NaAMt -mge6zo8x1tUfefrs6Z+ZA8ktTufqGLsAOAxr8zGqatVYQl6n+hlYsYcx3IoeuqSf -m1Z6tEazQ+tHLOr3DzP/yIyw2gWOFPxqW3u9CfeEsnvb++exfdKh0A6m71s3rwzB -tnYlm0KT52MAz+hShk3uX6hNVxtYfHcFSc1VTyMg68LHvj3pKoxY8VJFviBAtHvY -qcXoiNKrpxV0MmqBf+kAgWmPDT2tAUg1H0rcdOU7W/fKmVSz1MqpVXC22npp6mbP -IxY76lMvsd6flyt8pmghrlg3ie/kTa2ql1DDh2HySDP7wEoJ9LwTpuaefkuQLIJp -amxU/KKpAgMBAAECggEBAJbEKRPtFaQkOtsZyV7+qXD6TwiV4dIyQxpC4XCdNwcW -ONbJaJZ6KHTxifA1c10vJFLmySL/UohggQ2hYw4ESoIIfM5R5d7NkJ5xoIUcoJDI -CC7KJaOp4a6Ah2rQxDDUHUSfJDfiMGYV7nS4VWxaW+kmd65n3s6ZOxyBmaGXSl0L -kMocEQxoHXmt6nCJm7bI7fHBHrfNitRDLrb3FOS48D78xMEyeYkQ7Tuuu5vK5+y+ -4186THsZ1yMOlyskVPQ0k2SmiNfV4K14Y/wlJoFgyEJXYdV/frZMtWAerVgLk3FR -F+PqQFVU8ONt8TnIDnTD9sGwvnFk2rgcCD1syNc+9fECgYEA5EEpxcYsweFP49U6 -dydYjenm5HmjWDBxkqYI+hSvVDmfnk9xFYyDRbea2MQbj/Xm8dWezqdyGXy4svaN -2qXrqE7khC4YFYyrDkv3qIeHPd40/OhGeBXQSD2wXY9y793eG/W1llmW8QFIryO9 -far44M6QEToFq7kbnOfGoju6tOMCgYEAzO43a3vaA+v9LxyviXozOnfU5MnoIiKQ -MeJUY4vTfI1Zdfqp1oChaSW8b4dUW2aXX5Dq8k5kvinAlzZFFKEALnxT9pjcfF4H -Owaoc9P55ztCHxp6eSn/LhbCloIszFf98hGVc5gP4kYCPh4zpyNq65XMUYw4yh7N -e0kl3wXsrAMCgYEA4wPAZRiF2UqbJ3EiVfHHDFYPMzubbxG3U3BZS0iZXH53N3+x -bAo1YXiLxH2/H/4k9G9PJB+7xoeaNzwqt8T/zYSxmJkzkPM4Cd8acP5iTvEa6FKo -C7U+Uysvps4ONW0IA+zr7p4qFob9YFt+kmciYoxvEwMPMszHHtYSY7ZeKpsCgYEA -liSyVf2X7eeoyCusMH1nqx7AzB9iBCBupR291nFLsaWeNeJBLPdxSyhqtwvfslen -8Eys1nq5NNpCUIdidYrAJ07P9YxpfnUltwlZwgM8xT2VZFRyBvPOEmZ6ius1B0Iw -vHpFlTuD57SDUB+wmHRKkfBekiC6Otv2kK03If+lNyECgYBU7nfyrBUnym2e2QeV -j+y/xjK+95Dfd6qNWD5JiPqiRMdH5ew3LfTB+TDbXFyxv8NZV1CgtZZaunp8qHPD -CkLPedDGf4NGrtNkv28/mENMxFJgMyh2QnnZWHmRiNrQk0ooc6N36u/E4Aj40yDk -jCELRQAYr8VhAddlWgvR2FbOVw== ------END PRIVATE KEY----- diff --git a/camel-ids/ssl/cert.sh b/camel-ids/ssl/cert.sh deleted file mode 100755 index aa8ce5e74..000000000 --- a/camel-ids/ssl/cert.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2013-2015 with regard to distribution / exploitation: -# Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. -# - -cleanup(){ -echo "Cleanup unnecessary files" -[[ -f ${CONNECTOR_CSR} ]] && rm ${CONNECTOR_CSR} -[[ -f ${CONNECTOR_CONFIG} ]] && rm ${CONNECTOR_CONFIG} -[[ -f ${INDEX_FILE} ]] && rm ${INDEX_FILE} -[[ -f ${SERIAL_FILE} ]] && rm ${SERIAL_FILE} -[[ -f ${INDEX_FILE}.attr ]] && rm ${INDEX_FILE}.attr -[[ -f ${INDEX_FILE}.old ]] && rm ${INDEX_FILE}.old -[[ -f ${SERIAL_FILE}.old ]] && rm ${SERIAL_FILE}.old -[[ -f 01.pem ]] && rm 01.pem -} - -error_check(){ -if [ "$1" != "0" ]; then - echo "Error: $2" - cleanup - exit 1 -fi -} - -assert_file_exists(){ -if [ ! -f $1 ]; then - echo "Error: Missing file $1" - exit 1 -fi -} - -assert_file_not_exists(){ -if [ -f $1 ]; then - echo "Error: File $1 exists. Precautional exit" - exit 1 -fi -} - -# signing files -INDEX_FILE="certs/index.txt" -SERIAL_FILE="certs/serial.txt" - -#CA files -SUBCA_CONFIG="configs/openssl-subca.cnf" -SUBCA_CERT="ca/subca.cert" -SUBCA_KEY="ca/subca.key" -CACHAIN_CERT="ca/cachain.cert" - -#CONNECTOR certificate files -CONNECTOR_CONFIG="configs/openssl-connector.cnf" -CONNECTOR_CONFIG_TEMPLATE="configs/openssl-connector.cnf.template" -CONNECTOR_CSR="certs/$1.csr" -CONNECTOR_CERT="certs/$1.cert" -CONNECTOR_KEY="certs/$1.key" -CONNECTOR_P12="certs/$1.p12" - -if [ $# -eq 1 ] ; then - echo "One arguments supplied, which is good" -else - echo "Invalid number of arguments: $# (expected 1)" - echo "Usage: $0 filename" - exit 1 -fi - -cd $(dirname $0) -echo "Check if directory is clean" -assert_file_not_exists ${INDEX_FILE} -assert_file_not_exists ${SERIAL_FILE} -assert_file_not_exists ${CONNECTOR_CSR} -assert_file_not_exists ${CONNECTOR_KEY} -assert_file_not_exists ${CONNECTOR_CERT} -assert_file_not_exists ${CONNECTOR_CONFIG} -assert_file_not_exists ${CONNECTOR_P12} - -echo "Trying to find required files" -assert_file_exists ${SUBCA_KEY} -assert_file_exists ${SUBCA_CERT} -assert_file_exists ${SUBCA_CONFIG} -assert_file_exists ${CACHAIN_CERT} -assert_file_exists ${CONNECTOR_CONFIG_TEMPLATE} -echo "Successfully found requrired files" - -########## CONNECTOR CERT ########## -echo "Create connector config" -# copy template and set random values to uuid&serial -cp ${CONNECTOR_CONFIG_TEMPLATE} ${CONNECTOR_CONFIG} - -# create uuid and serial -UUID=$(cat /proc/sys/kernel/random/uuid) -SERIAL=$(cat /dev/urandom | tr -dc '0-9' | fold -w 16 | head -n 1) -sed -i "s/%%CONNECTOR_UUID%%/${UUID}/g" ${CONNECTOR_CONFIG} -sed -i "s/%%CONNECTOR_SERIAL%%/${SERIAL}/g" ${CONNECTOR_CONFIG} - -echo "Create dummy connector CSR" -openssl req -batch -config ${CONNECTOR_CONFIG} -newkey rsa:2048 -sha256 -nodes -out ${CONNECTOR_CSR} -outform PEM -keyout certs/$1.key -error_check $? "Failed to create test connector CSR" - -echo "Sign test connector CSR with sub CA certificate" -touch ${INDEX_FILE} -touch ${SERIAL_FILE} -echo '01' > ${SERIAL_FILE} -openssl ca -batch -config ${SUBCA_CONFIG} -policy signing_policy -extensions signing_req -out ${CONNECTOR_CERT} -infiles ${CONNECTOR_CSR} -error_check $? "Failed to sign connector CSR with CA certificate" - -echo "Verify newly created test connector certificate" -openssl verify -CAfile ${CACHAIN_CERT} ${CONNECTOR_CERT} -error_check $? "Failed to verify newly signed test certificate" - -echo "Create connector token with certifcate and key" -openssl pkcs12 -export -inkey ${CONNECTOR_KEY} -in ${CONNECTOR_CERT} -out ${CONNECTOR_P12} - -echo "Test certificates successfully created" -cleanup - -exit 0 diff --git a/camel-ids/ssl/certs/01.pem b/camel-ids/ssl/certs/01.pem deleted file mode 100644 index a8cca8756..000000000 --- a/camel-ids/ssl/certs/01.pem +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 1 (0x1) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 10:40:12 2017 GMT - Not After : Feb 15 10:40:12 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:de:1b:f0:c8:00:b2:da:14:de:2d:75:47:69:de: - 21:b1:0c:df:b8:3f:6b:3b:b9:a5:c1:79:b5:5e:e0: - 19:bc:f6:50:3c:86:bb:51:df:ce:f4:1b:39:0c:a4: - d2:33:94:e3:fa:10:8c:4c:ae:19:c2:ca:64:70:24: - 09:d4:8c:de:85:54:10:00:7e:fc:64:ea:59:5e:fb: - 60:e7:62:32:20:24:0d:63:05:ac:e2:a4:89:9e:6c: - 39:4d:cf:ed:5b:c9:74:2f:79:5d:71:86:7d:95:0c: - e6:c7:10:77:5e:c7:f8:aa:83:6b:03:73:45:ac:1d: - e5:52:5c:17:72:f9:c9:04:f8:7d:51:a5:51:d4:b8: - cc:69:0c:55:4f:88:0f:ff:f9:d5:2d:6d:12:66:33: - ec:d0:b9:9a:74:a5:b9:b8:8c:ea:52:a8:43:79:1a: - 82:fc:76:13:69:74:1e:83:04:99:4a:cb:ca:74:17: - 1d:a9:c1:aa:b1:c1:31:82:eb:8f:83:36:2f:4d:6f: - 14:ae:18:da:dc:0e:47:a2:78:a2:69:2d:ad:5e:a5: - 5b:e8:86:10:10:57:cc:3c:6b:16:02:33:99:16:a7: - 92:fc:8a:de:ce:91:ba:c6:38:21:cf:9c:71:6d:5e: - 7a:f2:84:08:9e:26:b5:eb:e9:c0:b1:ca:36:ce:26: - 26:77 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 0A:76:2C:69:51:01:75:28:A4:98:A5:68:84:88:95:70:EC:0D:0E:A5 - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:127.0.0.1, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19 - Signature Algorithm: sha256WithRSAEncryption - 5a:8f:2c:71:0e:84:38:31:68:eb:dc:7f:5f:5e:5e:ca:50:78: - fc:61:75:50:16:e2:1e:11:82:9f:6c:fe:7c:9b:0e:6d:bf:42: - 79:72:79:85:0e:ce:95:21:68:ac:83:a6:62:44:14:f2:f5:06: - 99:03:d1:f4:ba:06:fc:ca:0c:2a:8c:88:9e:b7:88:dc:df:3a: - a4:a5:b2:6e:2e:4f:0a:e4:23:95:a6:33:db:fa:45:e5:24:ed: - 6f:a4:62:09:33:7c:7f:ff:67:c9:fa:cb:fc:bd:d0:38:8c:a3: - 58:21:7b:2e:c3:92:46:c8:54:ff:31:44:04:36:b0:20:ff:3d: - d9:05:cb:cd:d8:4f:be:49:a1:2c:cb:50:88:1b:91:9f:f1:f3: - 57:d9:9a:9b:d3:1f:ea:c4:15:a3:da:7b:f4:84:01:b2:b9:0b: - c6:1b:fc:a3:2f:01:dc:60:5b:c3:7c:9e:76:4c:2c:d4:84:0c: - 3d:42:b4:48:f8:a3:72:34:b4:c5:40:ed:ba:7d:cc:8a:51:b9: - 8d:76:eb:8f:01:1a:0d:11:3a:b2:4c:d1:d0:84:38:21:bc:bc: - eb:52:65:b2:3a:cb:7e:e2:f0:f0:79:d0:40:92:74:7f:36:f8: - e6:85:fb:10:bd:67:ca:b6:25:79:c9:c1:7e:72:f2:48:82:d1: - 21:e1:90:03 ------BEGIN CERTIFICATE----- -MIIEjzCCA3egAwIBAgIBATANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTA0MDEyWhcNMTkwMjE1MTA0MDEyWjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDeG/DIALLaFN4tdUdp3iGx -DN+4P2s7uaXBebVe4Bm89lA8hrtR3870GzkMpNIzlOP6EIxMrhnCymRwJAnUjN6F -VBAAfvxk6lle+2DnYjIgJA1jBazipImebDlNz+1byXQveV1xhn2VDObHEHdex/iq -g2sDc0WsHeVSXBdy+ckE+H1RpVHUuMxpDFVPiA//+dUtbRJmM+zQuZp0pbm4jOpS -qEN5GoL8dhNpdB6DBJlKy8p0Fx2pwaqxwTGC64+DNi9NbxSuGNrcDkeieKJpLa1e -pVvohhAQV8w8axYCM5kWp5L8it7OkbrGOCHPnHFtXnryhAieJrXr6cCxyjbOJiZ3 -AgMBAAGjggFmMIIBYjAdBgNVHQ4EFgQUCnYsaVEBdSikmKVohIiVcOwNDqUwHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwWgYDVR0RBFMwUYIJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEfwAA -AYcECgECD4cECgECEIcECgECEYcECgECEocECgECEzANBgkqhkiG9w0BAQsFAAOC -AQEAWo8scQ6EODFo69x/X15eylB4/GF1UBbiHhGCn2z+fJsObb9CeXJ5hQ7OlSFo -rIOmYkQU8vUGmQPR9LoG/MoMKoyInreI3N86pKWybi5PCuQjlaYz2/pF5STtb6Ri -CTN8f/9nyfrL/L3QOIyjWCF7LsOSRshU/zFEBDawIP892QXLzdhPvkmhLMtQiBuR -n/HzV9mam9Mf6sQVo9p79IQBsrkLxhv8oy8B3GBbw3yedkws1IQMPUK0SPijcjS0 -xUDtun3MilG5jXbrjwEaDRE6skzR0IQ4Iby861JlsjrLfuLw8HnQQJJ0fzb45oX7 -EL1nyrYlecnBfnLySILRIeGQAw== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/02.pem b/camel-ids/ssl/certs/02.pem deleted file mode 100644 index adca2577a..000000000 --- a/camel-ids/ssl/certs/02.pem +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 2 (0x2) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 10:40:17 2017 GMT - Not After : Feb 15 10:40:17 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:ce:03:d3:06:e9:43:23:56:ac:26:13:70:ad:e9: - b6:ce:65:1f:1f:02:ff:06:7b:ef:d9:77:7e:b4:12: - 06:e5:0b:f9:50:6b:e2:d5:85:30:72:9f:b3:0c:9c: - f7:ff:a7:63:34:ad:58:5d:e5:c1:ce:09:f5:41:2b: - 6c:fb:1c:03:9a:61:67:b8:57:54:2f:f3:f9:55:10: - 90:28:73:14:1b:79:d3:5d:94:ac:54:63:1a:9b:53: - 80:97:69:b6:f9:91:a0:bb:8c:ee:c2:8c:ea:5b:1b: - bd:21:58:ef:a3:c6:c6:c6:4f:c2:1f:8d:a1:1c:79: - da:93:62:82:57:bf:f9:c4:8b:9d:ed:50:e4:0e:38: - 6d:70:1a:16:b3:34:c4:89:93:ad:4d:13:9d:c0:b3: - 51:05:42:98:5b:c1:8a:a2:09:49:f3:56:51:86:91: - f8:ac:9a:c4:a9:04:d6:cd:51:1d:1d:5c:d7:05:76: - ce:69:1a:03:ef:e3:03:05:de:d6:c5:1e:3a:7d:47: - a3:81:c9:10:58:0e:93:1c:5c:d4:ec:a2:94:6e:72: - 89:a1:29:79:20:1e:48:97:ec:8d:de:4e:30:b5:6f: - 92:c1:e6:8a:11:3b:21:57:5f:d9:4c:11:a2:62:a1: - 68:a0:b2:aa:31:ca:8a:30:79:40:9e:63:92:d3:0a: - c7:b3 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 76:76:0E:1C:DF:D0:9C:D7:E9:08:E2:93:2A:0C:D9:DE:D3:CA:2F:FA - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:127.0.0.1, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19 - Signature Algorithm: sha256WithRSAEncryption - 18:fe:4a:4c:82:a8:d6:c2:9b:1f:31:6c:de:32:d9:e7:12:b1: - f6:b1:88:a2:b5:99:8b:59:38:a4:da:58:1b:a0:f2:fd:4c:95: - 36:10:63:70:f5:5c:82:a5:3d:dd:dd:f4:d9:f9:35:a7:cb:8c: - e4:41:16:34:b8:2c:35:18:fe:74:d3:df:95:05:a4:0e:44:9f: - 85:37:20:90:fa:53:7e:0d:c3:2e:7a:6c:a1:4d:a4:db:9c:12: - 23:f5:49:e5:c1:95:03:11:20:e4:41:2a:3b:29:09:d9:bb:a9: - 20:d0:20:76:51:e9:76:c0:3d:de:06:e1:86:5d:42:bd:a9:b9: - 8e:dd:d9:23:ce:0a:8f:8c:0c:01:ed:aa:ac:63:1c:bc:27:82: - 03:66:4f:f7:2d:d7:4a:8b:d3:e4:2c:72:a4:46:37:5c:86:a5: - af:74:97:00:e7:74:40:60:1d:ba:32:6d:94:f8:0e:5a:c8:bc: - f6:f5:9e:b7:a8:30:ca:54:d8:a3:e5:7c:3e:37:75:1f:fc:10: - 82:47:a6:35:5b:ed:3e:cf:87:bc:2a:3a:e7:24:17:21:6c:96: - 7a:0c:95:59:18:92:6f:2f:7d:82:ae:80:50:50:cb:0a:73:d3: - 4e:10:9e:7a:73:ee:22:21:19:9b:f4:03:98:b9:c4:c4:f2:a3: - 81:94:eb:0d ------BEGIN CERTIFICATE----- -MIIEjzCCA3egAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTA0MDE3WhcNMTkwMjE1MTA0MDE3WjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDOA9MG6UMjVqwmE3Ct6bbO -ZR8fAv8Ge+/Zd360EgblC/lQa+LVhTByn7MMnPf/p2M0rVhd5cHOCfVBK2z7HAOa -YWe4V1Qv8/lVEJAocxQbedNdlKxUYxqbU4CXabb5kaC7jO7CjOpbG70hWO+jxsbG -T8IfjaEcedqTYoJXv/nEi53tUOQOOG1wGhazNMSJk61NE53As1EFQphbwYqiCUnz -VlGGkfismsSpBNbNUR0dXNcFds5pGgPv4wMF3tbFHjp9R6OByRBYDpMcXNTsopRu -comhKXkgHkiX7I3eTjC1b5LB5ooROyFXX9lMEaJioWigsqoxyooweUCeY5LTCsez -AgMBAAGjggFmMIIBYjAdBgNVHQ4EFgQUdnYOHN/QnNfpCOKTKgzZ3tPKL/owHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwWgYDVR0RBFMwUYIJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEfwAA -AYcECgECD4cECgECEIcECgECEYcECgECEocECgECEzANBgkqhkiG9w0BAQsFAAOC -AQEAGP5KTIKo1sKbHzFs3jLZ5xKx9rGIorWZi1k4pNpYG6Dy/UyVNhBjcPVcgqU9 -3d302fk1p8uM5EEWNLgsNRj+dNPflQWkDkSfhTcgkPpTfg3DLnpsoU2k25wSI/VJ -5cGVAxEg5EEqOykJ2bupINAgdlHpdsA93gbhhl1Cvam5jt3ZI84Kj4wMAe2qrGMc -vCeCA2ZP9y3XSovT5CxypEY3XIalr3SXAOd0QGAdujJtlPgOWsi89vWet6gwylTY -o+V8Pjd1H/wQgkemNVvtPs+HvCo65yQXIWyWegyVWRiSby99gq6AUFDLCnPTThCe -enPuIiEZm/QDmLnExPKjgZTrDQ== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/03.pem b/camel-ids/ssl/certs/03.pem deleted file mode 100644 index b0b0f90af..000000000 --- a/camel-ids/ssl/certs/03.pem +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 3 (0x3) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 10:53:39 2017 GMT - Not After : Feb 15 10:53:39 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c3:f9:1c:2b:cb:b5:40:da:a1:9d:04:20:64:77: - d2:f1:5a:ae:29:94:a0:6d:02:dc:92:be:c4:82:51: - a4:87:98:45:41:52:ee:aa:c0:af:8d:fe:13:03:20: - 63:e1:18:2d:b4:83:fd:d0:56:64:84:c3:3e:41:68: - 85:18:30:b5:9c:29:43:67:8b:70:6b:f2:0b:ee:2a: - cc:44:5b:98:7a:88:ae:cf:fc:5b:02:4d:15:57:06: - 63:1a:11:ab:99:81:61:e9:d5:ff:bd:04:c2:6c:ae: - c4:14:6b:a0:8a:88:f9:c8:54:ab:8f:56:49:1e:95: - cf:70:84:b6:b8:fb:fe:aa:f6:90:28:a0:e0:71:23: - 44:c3:a4:75:85:fb:c0:06:4e:cb:73:50:13:15:f6: - 7c:40:31:06:09:12:9d:ab:06:fa:ec:d0:6a:46:72: - 4f:2a:62:7b:bc:13:0d:29:d5:ce:88:27:98:25:25: - 5b:c0:41:57:49:b1:e3:95:e0:91:dc:8b:5f:9f:ae: - 34:77:e1:40:ec:92:03:d8:81:56:26:bf:f0:c1:ae: - 84:ba:7a:2a:0e:a5:b3:63:55:49:9c:dd:2d:2b:94: - 13:a8:05:ef:aa:79:5c:9e:18:d0:34:67:f8:f7:aa: - 79:e3:b9:83:ea:33:e7:08:94:5c:12:db:9b:bc:cc: - af:63 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 18:DE:0F:BE:24:E7:24:2C:92:F6:BB:35:21:E4:08:15:47:11:8A:0D - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:127.0.0.1, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19 - Signature Algorithm: sha256WithRSAEncryption - 77:81:53:e3:26:5f:a1:c0:57:66:31:6b:5f:e9:80:26:a8:ae: - 8d:4a:1a:cd:5f:75:16:a6:01:d3:ac:53:f8:67:5a:40:7f:4e: - 3d:6a:32:a3:7e:73:58:4b:bb:d4:52:44:3b:91:f8:f6:28:3f: - db:85:61:ff:56:96:48:46:bd:24:58:44:c0:d1:19:fc:8a:b3: - b3:5e:a9:69:83:7a:b3:03:dc:79:bb:b7:58:67:92:48:ed:be: - d3:47:a6:c7:2c:85:56:5d:c2:88:2d:19:1a:17:29:e5:3c:9e: - 36:63:64:6b:7f:1e:c9:16:3b:4c:0b:e5:fd:6a:aa:6e:ab:96: - 22:75:86:2f:29:8d:93:d5:c5:ba:9f:6e:e8:10:09:2a:eb:5a: - 19:6e:49:c1:28:43:a6:25:87:22:70:bb:fc:0e:10:e0:5f:f7: - ab:35:80:c6:b4:73:b6:ca:d0:68:21:5c:b7:0a:35:c4:8f:63: - 22:2f:2b:51:24:36:24:77:80:e4:4f:a5:72:8a:2e:19:74:8e: - dd:c5:34:7b:85:2e:e4:f8:86:0f:73:95:d9:53:0b:be:f1:9c: - 37:f5:59:ab:1e:1a:2b:42:df:56:46:c8:28:7b:76:af:9a:25: - 66:1c:1b:17:b8:1c:3f:f5:93:69:bb:70:7f:81:c4:78:ce:f6: - 83:64:cb:63 ------BEGIN CERTIFICATE----- -MIIEjzCCA3egAwIBAgIBAzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTA1MzM5WhcNMTkwMjE1MTA1MzM5WjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD+Rwry7VA2qGdBCBkd9Lx -Wq4plKBtAtySvsSCUaSHmEVBUu6qwK+N/hMDIGPhGC20g/3QVmSEwz5BaIUYMLWc -KUNni3Br8gvuKsxEW5h6iK7P/FsCTRVXBmMaEauZgWHp1f+9BMJsrsQUa6CKiPnI -VKuPVkkelc9whLa4+/6q9pAooOBxI0TDpHWF+8AGTstzUBMV9nxAMQYJEp2rBvrs -0GpGck8qYnu8Ew0p1c6IJ5glJVvAQVdJseOV4JHci1+frjR34UDskgPYgVYmv/DB -roS6eioOpbNjVUmc3S0rlBOoBe+qeVyeGNA0Z/j3qnnjuYPqM+cIlFwS25u8zK9j -AgMBAAGjggFmMIIBYjAdBgNVHQ4EFgQUGN4PviTnJCyS9rs1IeQIFUcRig0wHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwWgYDVR0RBFMwUYIJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEfwAA -AYcECgECD4cECgECEIcECgECEYcECgECEocECgECEzANBgkqhkiG9w0BAQsFAAOC -AQEAd4FT4yZfocBXZjFrX+mAJqiujUoazV91FqYB06xT+GdaQH9OPWoyo35zWEu7 -1FJEO5H49ig/24Vh/1aWSEa9JFhEwNEZ/Iqzs16paYN6swPcebu3WGeSSO2+00em -xyyFVl3CiC0ZGhcp5TyeNmNka38eyRY7TAvl/WqqbquWInWGLymNk9XFup9u6BAJ -KutaGW5JwShDpiWHInC7/A4Q4F/3qzWAxrRztsrQaCFctwo1xI9jIi8rUSQ2JHeA -5E+lcoouGXSO3cU0e4Uu5PiGD3OV2VMLvvGcN/VZqx4aK0LfVkbIKHt2r5olZhwb -F7gcP/WTabtwf4HEeM72g2TLYw== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/04.pem b/camel-ids/ssl/certs/04.pem deleted file mode 100644 index 933342149..000000000 --- a/camel-ids/ssl/certs/04.pem +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 4 (0x4) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 10:54:01 2017 GMT - Not After : Feb 15 10:54:01 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:bd:10:0f:51:77:42:72:56:bf:e5:59:9b:04:20: - 67:54:32:1f:22:26:60:cd:24:6f:50:f2:0b:c0:ff: - 7b:da:00:86:7b:54:3b:ec:d6:b4:f4:54:6e:97:38: - 82:9f:91:2c:1d:bb:14:0a:44:53:06:28:94:be:9e: - 1a:cc:9d:1d:90:36:57:b3:84:07:ac:bf:4b:f2:69: - 6c:54:26:6a:24:af:23:06:c3:f4:ae:0d:5e:93:4f: - 88:1a:97:39:ab:c1:67:29:54:23:54:44:94:58:59: - ba:ac:47:50:d7:9a:15:bc:d8:ff:98:51:e3:10:a7: - e9:db:1f:58:8d:4a:d8:5a:53:0a:f9:ff:3e:c6:d8: - 07:ff:23:07:76:1c:71:11:45:f2:8a:09:f7:4a:ee: - 9d:88:01:8a:d5:3f:e9:6d:7e:dc:4e:a2:7e:d2:bf: - 69:6c:f7:2a:d9:4d:c8:f6:39:bc:1c:03:5f:4f:85: - 33:24:1a:db:3d:bb:07:6b:01:d2:d6:4f:f8:1c:02: - 5c:66:dd:b4:31:b9:3e:a6:43:6c:4f:49:ea:e5:4c: - 50:7b:07:10:e5:66:42:18:7e:1b:e7:96:f7:ac:f9: - f9:59:ef:37:97:ef:bd:b9:ab:fa:8d:64:6a:32:6f: - 5c:05:96:3b:73:8e:75:6d:4e:a9:d7:c5:e0:b8:6c: - 6c:8b - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - CD:D4:B2:D4:BD:AA:83:CA:FA:45:26:E9:7D:E7:94:2C:EB:DD:20:87 - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:127.0.0.1, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19 - Signature Algorithm: sha256WithRSAEncryption - 04:ad:ff:ad:a0:7b:df:c2:47:d4:ae:69:0f:43:6d:be:93:e5: - bd:6a:1e:28:87:6e:63:08:a4:6d:59:e1:d2:79:be:84:f7:ca: - a5:87:b9:91:9b:4b:58:77:8d:2a:a0:32:fe:6f:1e:3e:0d:ff: - af:40:ba:94:7f:13:5d:8c:22:03:f5:de:13:3c:85:f1:72:59: - eb:03:e7:bc:95:4f:ac:29:a9:c4:ce:db:fe:38:6d:b4:7d:dc: - 99:7c:c2:f9:f4:c3:e6:9a:cc:13:f9:15:ce:5a:4c:b1:e9:85: - 29:32:a0:ed:2f:3d:ce:91:2e:d3:ba:7d:42:7e:74:3d:16:fc: - ff:4a:03:80:d6:e2:be:87:84:6b:d5:ff:1c:15:d2:45:9e:b4: - c8:8f:ce:ed:b6:3b:92:52:36:91:18:8d:fb:2c:d0:20:4a:ab: - 09:32:b4:c7:98:a8:de:57:73:2b:4f:34:cf:62:ac:2f:2e:59: - 06:13:9e:2d:42:0f:8c:c1:63:f7:44:87:ad:45:00:b7:26:95: - ce:80:87:96:d0:f9:69:21:cc:cd:6e:30:92:c8:76:93:a1:1a: - 09:eb:90:87:c8:2c:23:35:cb:14:6d:7d:ae:d3:f9:50:19:db: - 30:4e:93:ab:0e:ab:ab:fe:3c:db:39:52:34:f8:2f:87:b0:f7: - 11:e4:9a:34 ------BEGIN CERTIFICATE----- -MIIEjzCCA3egAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTA1NDAxWhcNMTkwMjE1MTA1NDAxWjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9EA9Rd0JyVr/lWZsEIGdU -Mh8iJmDNJG9Q8gvA/3vaAIZ7VDvs1rT0VG6XOIKfkSwduxQKRFMGKJS+nhrMnR2Q -NlezhAesv0vyaWxUJmokryMGw/SuDV6TT4galzmrwWcpVCNURJRYWbqsR1DXmhW8 -2P+YUeMQp+nbH1iNSthaUwr5/z7G2Af/Iwd2HHERRfKKCfdK7p2IAYrVP+ltftxO -on7Sv2ls9yrZTcj2ObwcA19PhTMkGts9uwdrAdLWT/gcAlxm3bQxuT6mQ2xPSerl -TFB7BxDlZkIYfhvnlves+flZ7zeX7725q/qNZGoyb1wFljtzjnVtTqnXxeC4bGyL -AgMBAAGjggFmMIIBYjAdBgNVHQ4EFgQUzdSy1L2qg8r6RSbpfeeULOvdIIcwHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwWgYDVR0RBFMwUYIJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEfwAA -AYcECgECD4cECgECEIcECgECEYcECgECEocECgECEzANBgkqhkiG9w0BAQsFAAOC -AQEABK3/raB738JH1K5pD0NtvpPlvWoeKIduYwikbVnh0nm+hPfKpYe5kZtLWHeN -KqAy/m8ePg3/r0C6lH8TXYwiA/XeEzyF8XJZ6wPnvJVPrCmpxM7b/jhttH3cmXzC -+fTD5prME/kVzlpMsemFKTKg7S89zpEu07p9Qn50PRb8/0oDgNbivoeEa9X/HBXS -RZ60yI/O7bY7klI2kRiN+yzQIEqrCTK0x5io3ldzK080z2KsLy5ZBhOeLUIPjMFj -90SHrUUAtyaVzoCHltD5aSHMzW4wksh2k6EaCeuQh8gsIzXLFG19rtP5UBnbME6T -qw6rq/482zlSNPgvh7D3EeSaNA== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/05.pem b/camel-ids/ssl/certs/05.pem deleted file mode 100644 index 404f47169..000000000 --- a/camel-ids/ssl/certs/05.pem +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 5 (0x5) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 10:54:09 2017 GMT - Not After : Feb 15 10:54:09 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c7:37:46:b3:57:62:e3:e3:70:8a:34:7f:48:ea: - f1:b6:34:c8:c7:ba:a5:ad:92:70:24:e4:2b:b2:2b: - db:75:57:43:a5:e8:95:69:3b:fd:9e:b7:c1:3e:34: - 49:b0:3d:5e:65:6d:ec:68:b1:b3:be:41:2e:df:dc: - 76:05:2f:b3:2e:42:f3:e8:8b:e3:25:c7:81:10:e3: - 4f:44:a9:7f:ab:40:1b:a8:c8:38:63:01:16:ff:81: - 01:a7:ac:4e:97:13:2d:92:60:f9:a4:32:3b:fc:8a: - 6c:4e:e5:ec:36:38:42:32:22:39:63:38:68:85:05: - 51:be:54:6c:11:fd:34:f0:ae:05:be:97:70:0d:bb: - 4e:9b:35:c1:b0:cf:bd:d0:bf:32:32:ad:d4:ce:1e: - dd:ab:69:5d:3f:69:b4:97:c1:6e:82:d8:65:65:f2: - 4c:ae:12:77:ba:33:7b:69:5e:0d:63:1a:fb:43:70: - a0:56:24:2b:51:83:87:fe:b1:db:fc:2d:99:9f:c8: - 6f:46:d5:28:03:0a:c2:43:aa:32:fc:61:1a:fc:5f: - 1b:53:b9:b7:fd:10:d2:5d:5b:81:16:49:f0:4a:21: - 9e:be:67:1d:94:89:84:ff:9f:d5:81:9a:97:20:96: - 78:be:47:c3:c3:51:bb:fd:3e:09:ec:36:3d:6f:1b: - 11:61 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 9F:E7:48:2B:6E:7F:EF:52:DB:18:5F:EE:31:C9:2F:0C:D6:9F:C6:7D - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:127.0.0.1, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19 - Signature Algorithm: sha256WithRSAEncryption - b3:73:00:e9:18:66:e9:57:12:e1:47:20:58:8e:ed:87:43:3b: - b4:fc:4c:63:0c:4e:6e:73:ce:9f:ec:6a:49:e9:2a:fe:a4:5a: - 02:5b:ae:aa:ed:bc:0c:00:07:82:5e:09:e1:fc:23:6e:bb:b8: - 71:7c:09:4b:ac:9b:5b:2f:6b:84:4c:45:a3:60:18:b0:69:d3: - fb:d6:79:c7:7a:78:34:bc:29:ec:61:fd:b3:7c:d0:7b:79:5e: - eb:94:cb:ec:9e:32:41:64:d5:79:3f:42:56:14:22:f8:5d:fe: - 28:67:0c:f3:c6:b0:8f:23:db:61:6d:5a:7b:88:0f:37:b8:ec: - 76:90:ef:88:20:00:37:c4:d9:56:34:10:56:2c:54:8a:4a:55: - 7b:a4:e5:2d:82:84:a9:5a:fa:77:21:b9:63:9e:bc:8b:5a:f3: - 39:bc:9f:c5:da:05:e8:e8:cb:c0:d8:63:81:8f:d4:17:ff:08: - 8d:db:1e:0d:a0:46:03:10:f0:36:e3:ce:11:36:0f:a8:3d:7c: - af:3f:6c:f7:38:a0:62:a3:da:9e:ea:c2:b0:34:ac:43:8d:72: - 97:89:21:75:fe:6b:12:68:18:2e:e5:b9:07:25:b4:55:bc:c4: - 65:55:a4:cc:b8:d3:ba:e9:39:76:fb:43:56:3a:18:83:4a:66: - be:2b:f3:7f ------BEGIN CERTIFICATE----- -MIIEjzCCA3egAwIBAgIBBTANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTA1NDA5WhcNMTkwMjE1MTA1NDA5WjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHN0azV2Lj43CKNH9I6vG2 -NMjHuqWtknAk5CuyK9t1V0Ol6JVpO/2et8E+NEmwPV5lbexosbO+QS7f3HYFL7Mu -QvPoi+Mlx4EQ409EqX+rQBuoyDhjARb/gQGnrE6XEy2SYPmkMjv8imxO5ew2OEIy -IjljOGiFBVG+VGwR/TTwrgW+l3ANu06bNcGwz73QvzIyrdTOHt2raV0/abSXwW6C -2GVl8kyuEne6M3tpXg1jGvtDcKBWJCtRg4f+sdv8LZmfyG9G1SgDCsJDqjL8YRr8 -XxtTubf9ENJdW4EWSfBKIZ6+Zx2UiYT/n9WBmpcglni+R8PDUbv9PgnsNj1vGxFh -AgMBAAGjggFmMIIBYjAdBgNVHQ4EFgQUn+dIK25/71LbGF/uMckvDNafxn0wHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwWgYDVR0RBFMwUYIJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEfwAA -AYcECgECD4cECgECEIcECgECEYcECgECEocECgECEzANBgkqhkiG9w0BAQsFAAOC -AQEAs3MA6Rhm6VcS4UcgWI7th0M7tPxMYwxObnPOn+xqSekq/qRaAluuqu28DAAH -gl4J4fwjbru4cXwJS6ybWy9rhExFo2AYsGnT+9Z5x3p4NLwp7GH9s3zQe3le65TL -7J4yQWTVeT9CVhQi+F3+KGcM88awjyPbYW1ae4gPN7jsdpDviCAAN8TZVjQQVixU -ikpVe6TlLYKEqVr6dyG5Y568i1rzObyfxdoF6OjLwNhjgY/UF/8IjdseDaBGAxDw -NuPOETYPqD18rz9s9zigYqPanurCsDSsQ41yl4khdf5rEmgYLuW5ByW0VbzEZVWk -zLjTuuk5dvtDVjoYg0pmvivzfw== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/06.pem b/camel-ids/ssl/certs/06.pem deleted file mode 100644 index 23a840038..000000000 --- a/camel-ids/ssl/certs/06.pem +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 6 (0x6) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 11:48:45 2017 GMT - Not After : Feb 15 11:48:45 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:da:df:c7:09:ce:93:90:3e:75:e6:2d:33:22:0a: - d5:35:a6:c6:53:4f:eb:d7:bd:a5:e4:8b:13:3c:8d: - a6:e8:bb:57:34:7e:41:1a:af:5d:46:14:77:f6:b3: - 22:91:84:4b:42:e4:7f:9d:1d:48:68:fd:dd:bd:ef: - 7e:4b:a5:49:7a:86:05:18:e0:f6:a3:6e:d2:cf:b3: - 37:4f:40:4d:71:2b:6b:79:8c:e4:7d:e6:d4:45:c6: - 3f:b6:f4:d2:2d:98:eb:aa:b4:e8:fd:df:78:f4:58: - 7d:2f:2c:74:8d:bc:6b:c1:e5:34:66:90:8c:4d:87: - 94:7b:b2:10:67:8a:3b:d9:33:16:1f:cc:c5:c1:17: - 66:9d:2d:e2:bf:21:2a:b7:ca:38:2f:e6:89:2e:cf: - d7:30:50:49:73:f1:c1:e1:b9:78:26:e2:e7:35:d5: - 0f:8d:7b:7b:9e:ba:b9:e9:18:6e:f3:b3:6e:44:a6: - 42:23:54:7e:84:ca:64:a0:1f:e5:ec:57:7a:94:b1: - 50:13:b2:43:1f:0f:aa:dc:0f:14:0f:5e:f0:72:ff: - 5a:ac:22:bb:90:67:d7:c6:05:e3:3f:46:df:6e:15: - 31:66:6e:c6:79:fa:fe:9b:62:80:da:7e:9a:0e:63: - f9:bc:64:b4:79:db:9d:ff:a0:5f:8d:4a:4f:7a:19: - 6e:8d - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 20:FB:F1:B6:EB:55:5D:9C:AB:BE:6E:E1:3F:B3:A9:45:16:D6:1E:2E - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:127.0.0.1, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19, IP Address:10.1.2.20, IP Address:10.1.2.21 - Signature Algorithm: sha256WithRSAEncryption - 19:d3:82:26:88:34:34:1c:3c:b8:5c:9b:51:c9:2a:0a:6b:be: - 1d:e7:42:30:1e:57:1e:55:54:44:42:34:9a:0f:71:63:29:f6: - 6a:46:a9:b7:d2:be:29:75:5f:9b:6f:d5:99:8e:36:bc:ff:0c: - cd:27:37:5c:4e:f5:a9:da:5d:60:f1:39:15:62:75:5a:8a:ef: - 24:89:e2:ad:f0:b8:e2:80:59:ef:78:b7:15:77:8e:3a:21:3d: - 64:83:71:13:9a:c0:55:da:98:a5:e0:e8:96:7b:ca:2a:12:1d: - fa:d8:e1:cc:8c:b6:4b:a0:0c:f1:a4:5e:be:84:a7:45:a0:f2: - 47:73:bf:cc:3b:d8:d3:3f:3a:25:c8:11:fc:bd:ef:ca:24:10: - 22:06:b7:b7:48:79:bf:8f:8f:d1:4b:f3:5d:ff:b1:04:e6:6c: - 16:ec:fe:aa:01:10:b4:a2:e2:a2:a8:b1:fe:61:8c:6f:29:98: - 7f:9a:32:65:dd:a5:1e:5c:53:b7:c6:9f:a6:c9:68:2e:73:42: - 2e:43:7f:1b:3b:a2:e8:80:d5:9b:06:b5:38:73:b2:15:ae:6f: - 78:bc:95:64:5f:b4:6a:ce:b5:53:e4:30:2d:b8:0e:2f:57:ae: - 57:62:26:43:94:81:1c:73:63:57:9c:c2:29:1f:06:14:c4:fa: - 52:3a:99:e4 ------BEGIN CERTIFICATE----- -MIIEmzCCA4OgAwIBAgIBBjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTE0ODQ1WhcNMTkwMjE1MTE0ODQ1WjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa38cJzpOQPnXmLTMiCtU1 -psZTT+vXvaXkixM8jabou1c0fkEar11GFHf2syKRhEtC5H+dHUho/d29735LpUl6 -hgUY4PajbtLPszdPQE1xK2t5jOR95tRFxj+29NItmOuqtOj933j0WH0vLHSNvGvB -5TRmkIxNh5R7shBnijvZMxYfzMXBF2adLeK/ISq3yjgv5okuz9cwUElz8cHhuXgm -4uc11Q+Ne3ueurnpGG7zs25EpkIjVH6EymSgH+XsV3qUsVATskMfD6rcDxQPXvBy -/1qsIruQZ9fGBeM/Rt9uFTFmbsZ5+v6bYoDafpoOY/m8ZLR5253/oF+NSk96GW6N -AgMBAAGjggFyMIIBbjAdBgNVHQ4EFgQUIPvxtutVXZyrvm7hP7OpRRbWHi4wHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwZgYDVR0RBF8wXYIJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEfwAA -AYcECgECD4cECgECEIcECgECEYcECgECEocECgECE4cECgECFIcECgECFTANBgkq -hkiG9w0BAQsFAAOCAQEAGdOCJog0NBw8uFybUckqCmu+HedCMB5XHlVUREI0mg9x -Yyn2akapt9K+KXVfm2/VmY42vP8MzSc3XE71qdpdYPE5FWJ1WorvJInirfC44oBZ -73i3FXeOOiE9ZINxE5rAVdqYpeDolnvKKhId+tjhzIy2S6AM8aRevoSnRaDyR3O/ -zDvY0z86JcgR/L3vyiQQIga3t0h5v4+P0UvzXf+xBOZsFuz+qgEQtKLioqix/mGM -bymYf5oyZd2lHlxTt8afpsloLnNCLkN/Gzui6IDVmwa1OHOyFa5veLyVZF+0as61 -U+QwLbgOL1euV2ImQ5SBHHNjV5zCKR8GFMT6UjqZ5A== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/07.pem b/camel-ids/ssl/certs/07.pem deleted file mode 100644 index f652d5e97..000000000 --- a/camel-ids/ssl/certs/07.pem +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 7 (0x7) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 11:48:51 2017 GMT - Not After : Feb 15 11:48:51 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:b1:b0:1a:4c:3d:5a:37:5a:72:9b:a6:3f:4f:44: - 0c:54:5a:6b:03:c0:52:9b:23:9c:ce:44:86:38:98: - 63:ea:81:03:a9:8a:38:4c:82:6b:11:56:98:2a:36: - 34:84:3f:c7:cf:18:ea:3f:d9:c0:19:cc:e4:bf:c2: - 49:e5:08:a7:b7:f3:58:ab:f4:e8:43:83:6a:4e:84: - 11:4c:a1:8b:b1:09:0f:ce:1f:cb:1a:73:fa:68:b9: - d0:fd:d1:ca:69:4a:55:52:41:f1:a1:70:1d:88:c0: - 58:9b:24:e2:5f:f6:96:eb:03:db:91:c6:27:8b:12: - 45:53:a3:f4:61:9c:51:ba:50:47:37:60:2b:dc:d4: - 18:58:57:7a:dc:16:f4:ce:ea:22:a3:48:3b:f0:a5: - 42:52:34:05:da:1e:5e:85:da:32:3a:44:e7:38:9b: - dc:ba:24:dd:a8:05:61:db:8d:7c:79:25:34:bf:64: - 33:88:97:70:e8:5d:65:f2:70:c1:ad:e3:2a:0a:41: - bf:f8:9f:15:7f:c4:d5:7f:f7:88:e1:92:3a:7d:34: - 4e:4b:ee:36:9b:5e:06:1a:07:26:3a:78:23:78:e6: - 5f:42:1f:e9:e3:80:02:73:a9:84:56:68:47:1a:68: - 97:99:f7:4d:ad:29:2b:f3:79:2d:02:58:0b:a7:2b: - f9:5b - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - AB:11:36:B5:A6:D9:07:02:0C:37:9D:82:A9:43:C5:19:06:76:C1:06 - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:127.0.0.1, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19, IP Address:10.1.2.20, IP Address:10.1.2.21 - Signature Algorithm: sha256WithRSAEncryption - 62:e0:84:9a:e4:cb:93:c1:76:a2:99:88:30:5e:1d:8c:53:7c: - e2:19:96:c7:d8:04:cb:32:1b:a5:53:23:0e:b4:1a:2d:c3:97: - 9c:83:53:99:c6:bb:39:5c:b4:10:22:19:90:6d:e2:fe:f4:38: - a1:dc:c4:08:fc:02:e1:c2:71:7a:4d:dd:a8:2a:23:7d:42:bb: - f6:b9:ff:96:ca:87:19:a4:7f:c8:db:3c:13:50:a3:30:d8:76: - 12:b6:47:43:46:96:76:5e:d2:86:ed:f8:cb:c2:d9:f7:91:55: - 3c:20:b9:d2:e1:63:c9:5c:6d:0d:5d:7d:10:95:18:fb:79:8c: - f5:c6:51:5a:ec:de:13:16:87:27:7a:7b:60:55:5c:4d:af:2e: - e3:a7:b2:88:12:96:32:8f:8c:46:50:1b:79:2e:26:cb:ad:32: - 63:6d:a8:5b:c5:f2:92:a8:62:31:90:f9:6a:f9:d1:8c:6d:eb: - 15:03:9d:df:e7:8b:a0:99:d9:c1:8e:ff:45:d9:3a:5f:f0:7d: - 86:40:2e:78:7b:16:2f:29:5b:7a:b9:a4:75:a7:5b:b9:86:84: - 9a:40:b5:fb:7b:ee:98:11:33:0a:a0:fe:26:3b:56:57:5e:a8: - 83:9c:9c:3d:e3:da:20:fc:d4:3e:c3:cf:5d:33:77:fc:2e:8c: - 1b:12:0a:28 ------BEGIN CERTIFICATE----- -MIIEmzCCA4OgAwIBAgIBBzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTE0ODUxWhcNMTkwMjE1MTE0ODUxWjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxsBpMPVo3WnKbpj9PRAxU -WmsDwFKbI5zORIY4mGPqgQOpijhMgmsRVpgqNjSEP8fPGOo/2cAZzOS/wknlCKe3 -81ir9OhDg2pOhBFMoYuxCQ/OH8sac/poudD90cppSlVSQfGhcB2IwFibJOJf9pbr -A9uRxieLEkVTo/RhnFG6UEc3YCvc1BhYV3rcFvTO6iKjSDvwpUJSNAXaHl6F2jI6 -ROc4m9y6JN2oBWHbjXx5JTS/ZDOIl3DoXWXycMGt4yoKQb/4nxV/xNV/94jhkjp9 -NE5L7jabXgYaByY6eCN45l9CH+njgAJzqYRWaEcaaJeZ902tKSvzeS0CWAunK/lb -AgMBAAGjggFyMIIBbjAdBgNVHQ4EFgQUqxE2tabZBwIMN52CqUPFGQZ2wQYwHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwZgYDVR0RBF8wXYIJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEfwAA -AYcECgECD4cECgECEIcECgECEYcECgECEocECgECE4cECgECFIcECgECFTANBgkq -hkiG9w0BAQsFAAOCAQEAYuCEmuTLk8F2opmIMF4djFN84hmWx9gEyzIbpVMjDrQa -LcOXnINTmca7OVy0ECIZkG3i/vQ4odzECPwC4cJxek3dqCojfUK79rn/lsqHGaR/ -yNs8E1CjMNh2ErZHQ0aWdl7Shu34y8LZ95FVPCC50uFjyVxtDV19EJUY+3mM9cZR -WuzeExaHJ3p7YFVcTa8u46eyiBKWMo+MRlAbeS4my60yY22oW8XykqhiMZD5avnR -jG3rFQOd3+eLoJnZwY7/Rdk6X/B9hkAueHsWLylbermkdadbuYaEmkC1+3vumBEz -CqD+JjtWV16og5ycPePaIPzUPsPPXTN3/C6MGxIKKA== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/08.pem b/camel-ids/ssl/certs/08.pem deleted file mode 100644 index c2fae1a4d..000000000 --- a/camel-ids/ssl/certs/08.pem +++ /dev/null @@ -1,97 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 8 (0x8) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 12:20:54 2017 GMT - Not After : Feb 15 12:20:54 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:ab:5e:79:16:ab:09:6c:01:82:39:85:35:68:89: - 5e:97:80:17:f4:ce:82:49:72:a2:c8:f0:a0:4d:29: - 1b:fd:fb:da:72:e0:e3:43:f6:bf:ab:a6:5c:18:a8: - e0:e1:9f:6d:ae:18:ed:46:60:d1:62:71:14:a0:91: - 24:2c:dd:23:77:5c:6c:16:23:b5:7a:17:23:8a:04: - f1:61:17:10:84:8f:9f:b0:55:1d:f5:51:6b:fb:39: - e0:3b:e2:df:e4:a2:b6:88:5e:4a:62:cb:38:1f:5d: - 97:46:24:06:f2:57:7d:0b:fd:44:9a:a2:6c:b5:62: - 75:0f:09:ff:c6:50:ba:23:3f:a9:72:51:5f:b7:56: - e8:de:9c:c2:a8:e3:29:60:af:83:3f:a5:e4:f6:f8: - 62:6f:9e:0e:ed:ab:0e:72:04:da:45:cc:60:9e:d2: - f3:ea:f0:e3:8d:50:72:ef:37:6d:74:cc:8e:14:ce: - 25:58:35:18:50:37:56:f5:af:5c:9e:41:d0:3c:e0: - 64:d4:a3:e6:f9:3d:b0:1a:a8:90:94:53:9b:bf:e2: - 04:22:40:71:c5:ab:10:9a:16:9c:00:71:ec:9e:0f: - 87:ba:95:18:ba:df:de:8e:2d:5c:0a:37:ab:3f:7a: - 37:05:cb:05:cd:ff:8e:6e:c5:b0:db:88:58:04:c1: - 07:31 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 7F:87:F0:CE:E0:E9:9F:EC:D8:4F:98:EF:BE:3F:D4:30:A0:BC:80:F2 - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:0.0.0.0 - Signature Algorithm: sha256WithRSAEncryption - 8a:30:c6:95:9d:5f:3d:e1:73:1a:94:62:0e:81:07:99:ac:bd: - d8:12:27:5d:29:1a:ea:5f:ab:eb:6d:1e:ae:df:38:ef:39:28: - f3:25:cf:3a:06:e1:01:c7:ef:e7:21:98:b6:22:22:f5:a6:c2: - 90:4f:fb:45:17:75:f4:da:c5:2b:ca:62:4e:bc:a4:48:ed:e7: - d3:9e:38:3a:ca:de:90:9d:b8:fe:7d:c9:28:1a:39:96:24:b3: - 24:78:23:3b:1d:ef:e5:4c:8f:2a:c9:b8:a5:08:c3:43:47:a6: - a6:1f:ab:8d:bb:07:ce:6a:77:f5:d6:65:de:78:fb:ca:ff:36: - 80:09:2f:63:19:65:6a:b7:39:2e:f8:7f:6c:4a:79:31:9d:d6: - e4:b7:05:07:3f:72:82:70:76:51:8b:ec:8b:98:5f:38:ed:30: - ad:8f:a0:b5:17:99:92:fc:1a:5b:e6:c6:b2:f7:d9:f3:71:8a: - e5:b5:ba:47:64:00:15:f8:88:90:04:ff:13:ae:08:6c:0c:a6: - e8:61:e6:32:4c:4b:d1:d8:50:92:a0:65:a7:f6:da:d2:35:7e: - c9:52:ba:2a:79:c7:4a:18:1a:80:fc:90:c2:f4:95:d3:ca:1f: - 68:36:26:da:08:81:06:74:80:68:24:23:d8:24:55:44:d6:5f: - a3:b3:30:b8 ------BEGIN CERTIFICATE----- -MIIEcTCCA1mgAwIBAgIBCDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTIyMDU0WhcNMTkwMjE1MTIyMDU0WjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrXnkWqwlsAYI5hTVoiV6X -gBf0zoJJcqLI8KBNKRv9+9py4OND9r+rplwYqODhn22uGO1GYNFicRSgkSQs3SN3 -XGwWI7V6FyOKBPFhFxCEj5+wVR31UWv7OeA74t/koraIXkpiyzgfXZdGJAbyV30L -/USaomy1YnUPCf/GULojP6lyUV+3VujenMKo4ylgr4M/peT2+GJvng7tqw5yBNpF -zGCe0vPq8OONUHLvN210zI4UziVYNRhQN1b1r1yeQdA84GTUo+b5PbAaqJCUU5u/ -4gQiQHHFqxCaFpwAceyeD4e6lRi6396OLVwKN6s/ejcFywXN/45uxbDbiFgEwQcx -AgMBAAGjggFIMIIBRDAdBgNVHQ4EFgQUf4fwzuDpn+zYT5jvvj/UMKC8gPIwHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwPAYDVR0RBDUwM4IJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEAAAA -ADANBgkqhkiG9w0BAQsFAAOCAQEAijDGlZ1fPeFzGpRiDoEHmay92BInXSka6l+r -620ert847zko8yXPOgbhAcfv5yGYtiIi9abCkE/7RRd19NrFK8piTrykSO3n0544 -OsrekJ24/n3JKBo5liSzJHgjOx3v5UyPKsm4pQjDQ0emph+rjbsHzmp39dZl3nj7 -yv82gAkvYxllarc5Lvh/bEp5MZ3W5LcFBz9ygnB2UYvsi5hfOO0wrY+gtReZkvwa -W+bGsvfZ83GK5bW6R2QAFfiIkAT/E64IbAym6GHmMkxL0dhQkqBlp/ba0jV+yVK6 -KnnHShgagPyQwvSV08ofaDYm2giBBnSAaCQj2CRVRNZfo7MwuA== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/09.pem b/camel-ids/ssl/certs/09.pem deleted file mode 100644 index ea53d184b..000000000 --- a/camel-ids/ssl/certs/09.pem +++ /dev/null @@ -1,97 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 9 (0x9) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 12:21:04 2017 GMT - Not After : Feb 15 12:21:04 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:cd:0a:c5:5d:d9:ec:cd:c4:88:f9:b3:54:23:b1: - 35:17:f0:46:54:a2:23:1e:ce:62:23:a6:e2:cb:f6: - 82:f6:a1:25:36:5d:af:fc:59:4c:fb:ba:a4:7b:1f: - e9:14:55:cb:d3:76:6c:97:b3:4b:54:d5:9f:7b:b8: - 10:34:e2:01:00:ba:05:87:c3:a3:42:f7:9a:1c:03: - cf:5f:35:0f:2c:89:91:f7:c9:8c:e9:9a:c4:2c:0b: - 2f:40:c8:8e:13:39:80:ed:37:e7:fa:13:b8:f3:dc: - 60:58:61:7e:ff:cf:41:0d:7e:0a:c4:0c:04:73:37: - fc:33:2c:84:91:27:d2:81:c5:63:45:94:00:67:26: - 6f:b8:d8:22:0d:83:b2:4b:55:0a:83:8a:e0:a1:1d: - 80:bb:76:6c:57:b8:ce:0c:ef:a5:a8:69:76:08:25: - 13:a1:63:c1:03:3e:39:71:70:fd:c9:f2:e8:97:a2: - e5:6c:c5:18:f4:45:6a:33:25:db:98:56:71:68:e9: - a7:7b:99:a2:a3:8e:46:8c:68:5e:bd:6c:c2:e4:0a: - 66:49:db:af:07:57:ab:57:af:17:1f:f7:a3:11:01: - 9b:37:f1:ad:75:29:a4:5c:13:67:74:21:2e:90:a3: - 63:ad:1b:4e:71:e5:29:40:53:1e:b8:31:ea:c9:14: - 96:4d - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - B1:5B:E0:F3:B0:3C:39:C8:35:57:EF:B2:1A:4B:40:96:7A:40:5C:82 - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:0.0.0.0 - Signature Algorithm: sha256WithRSAEncryption - 7a:c2:05:14:14:5b:c3:a9:a5:4f:d0:63:be:bd:e8:a4:b5:d3: - bc:f6:ed:b1:74:6e:5c:b1:80:3a:03:0c:69:1e:a7:57:17:c8: - 33:ab:62:e7:e5:39:8f:78:f0:2a:c7:72:f1:57:25:6d:2a:29: - d7:a4:14:67:7f:55:db:c3:99:8c:13:8e:29:33:65:80:9d:2c: - e8:d4:63:76:6b:91:da:50:2d:0c:a2:97:b8:03:80:32:3d:9b: - ce:31:ba:d9:7a:b9:c5:e3:53:dd:15:54:c6:84:9d:1c:e5:87: - 06:94:2d:bc:97:e5:8f:a9:d6:66:5f:55:5c:84:0d:3e:ea:f1: - 36:ff:92:f4:4e:68:3d:bf:3c:07:53:96:38:6f:30:b0:29:47: - 0d:59:b8:e4:f0:74:b0:60:a9:9c:b4:fd:6e:17:0d:47:b3:de: - f2:c7:2a:a2:c8:66:c9:8b:96:da:4b:c6:b2:fd:72:09:1c:f4: - 51:7d:2c:9e:de:f4:d5:73:d3:6c:f4:98:02:a9:05:a8:4a:b5: - 31:dd:3a:b6:db:a2:41:5d:0d:94:3d:8e:b6:f7:91:cb:66:02: - e3:fa:c7:05:e0:02:33:b1:f6:dd:c8:ce:14:0b:9f:8d:0c:67: - 76:a0:93:9e:8e:b1:bb:f9:00:b3:2f:e0:26:02:47:2c:88:e4: - 54:ff:3b:f9 ------BEGIN CERTIFICATE----- -MIIEcTCCA1mgAwIBAgIBCTANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTIyMTA0WhcNMTkwMjE1MTIyMTA0WjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNCsVd2ezNxIj5s1QjsTUX -8EZUoiMezmIjpuLL9oL2oSU2Xa/8WUz7uqR7H+kUVcvTdmyXs0tU1Z97uBA04gEA -ugWHw6NC95ocA89fNQ8siZH3yYzpmsQsCy9AyI4TOYDtN+f6E7jz3GBYYX7/z0EN -fgrEDARzN/wzLISRJ9KBxWNFlABnJm+42CINg7JLVQqDiuChHYC7dmxXuM4M76Wo -aXYIJROhY8EDPjlxcP3J8uiXouVsxRj0RWozJduYVnFo6ad7maKjjkaMaF69bMLk -CmZJ268HV6tXrxcf96MRAZs38a11KaRcE2d0IS6Qo2OtG05x5SlAUx64MerJFJZN -AgMBAAGjggFIMIIBRDAdBgNVHQ4EFgQUsVvg87A8Ocg1V++yGktAlnpAXIIwHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwPAYDVR0RBDUwM4IJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEAAAA -ADANBgkqhkiG9w0BAQsFAAOCAQEAesIFFBRbw6mlT9Bjvr3opLXTvPbtsXRuXLGA -OgMMaR6nVxfIM6ti5+U5j3jwKsdy8VclbSop16QUZ39V28OZjBOOKTNlgJ0s6NRj -dmuR2lAtDKKXuAOAMj2bzjG62Xq5xeNT3RVUxoSdHOWHBpQtvJflj6nWZl9VXIQN -PurxNv+S9E5oPb88B1OWOG8wsClHDVm45PB0sGCpnLT9bhcNR7Pe8scqoshmyYuW -2kvGsv1yCRz0UX0snt701XPTbPSYAqkFqEq1Md06ttuiQV0NlD2OtveRy2YC4/rH -BeACM7H23cjOFAufjQxndqCTno6xu/kAsy/gJgJHLIjkVP87+Q== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/0A.pem b/camel-ids/ssl/certs/0A.pem deleted file mode 100644 index 8e5e59f82..000000000 --- a/camel-ids/ssl/certs/0A.pem +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 10 (0xa) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 12:33:10 2017 GMT - Not After : Feb 15 12:33:10 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c1:46:79:a9:fc:24:16:92:7f:b1:76:fa:93:3d: - 56:49:a1:3f:db:08:66:b1:3d:c5:ad:6a:4a:45:eb: - f1:5f:e7:2d:9a:96:1b:2f:05:97:57:27:dd:2d:ee: - 5d:8c:ac:be:9b:f0:2e:26:5f:18:21:22:b5:41:f3: - a6:65:8b:6e:84:93:df:ef:e4:2d:a8:cd:d5:ff:55: - 3c:1f:9d:2c:77:43:3f:b4:c8:4c:18:25:5b:39:9f: - b1:e9:95:9a:d6:5a:a7:07:60:d6:8b:cd:17:6b:86: - 98:67:86:45:49:df:f5:ea:29:7e:76:e3:82:bf:e0: - 27:29:c8:cc:82:22:ba:8e:6d:73:b1:8b:03:d5:2a: - 19:69:c5:97:7b:d6:cc:fc:90:bf:0f:2e:4f:ec:ab: - 26:0e:01:c6:f5:f2:54:54:4e:74:54:34:bc:de:14: - 5d:2d:d4:00:a1:dc:88:84:d8:40:0b:1a:17:cb:7b: - 22:8a:ad:3d:ac:9b:0d:64:7d:51:64:12:50:76:db: - bf:6a:44:87:b5:33:08:28:c4:8f:88:24:b1:c2:a9: - ba:e7:58:e7:cd:99:c0:c3:05:1c:4a:31:fc:73:df: - 71:41:ae:09:e8:6a:31:69:29:7b:ac:fe:48:fc:6a: - 0a:f0:6c:dc:8e:24:10:6b:48:a5:a3:af:ee:43:d1: - 8e:ad - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 22:85:57:AC:8D:C9:E7:50:66:B8:BA:FF:FB:BC:15:78:34:52:F2:8C - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:0.0.0.0, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19, IP Address:10.1.2.20, IP Address:10.1.2.21, IP Address:10.1.2.22 - Signature Algorithm: sha256WithRSAEncryption - 52:f7:94:16:44:2a:c2:e3:ef:b4:91:93:61:19:d2:f3:46:b8: - 8f:5e:89:1c:37:d5:f0:8d:3b:eb:30:47:c2:d9:a5:fd:c1:48: - 17:b9:1e:8a:d3:a7:2d:06:43:e5:39:42:32:9c:f1:a9:47:f1: - 24:7b:da:af:ae:97:e3:bb:8c:98:b0:33:87:f3:3b:43:22:99: - f5:42:b6:1f:62:03:e7:16:f6:61:ba:d6:b7:0a:28:3d:19:6e: - d7:dc:c8:7e:f2:0b:97:46:1a:d8:95:71:8d:da:22:45:d6:89: - e8:4b:e6:9d:cb:5f:92:80:26:a3:a9:6c:fc:7c:80:fe:e3:ed: - 8c:f6:9d:77:4d:06:34:69:95:95:bd:fe:f0:5e:57:8e:ee:85: - 65:57:d7:c9:18:77:9c:58:c3:e4:eb:a4:07:11:f0:41:61:af: - 4c:40:24:d3:03:01:89:85:59:09:60:76:ec:ae:e2:53:cf:8f: - be:a9:0f:c5:99:a5:3a:3a:df:73:22:49:f5:d9:da:43:48:a8: - d5:38:95:77:00:3c:1e:2d:86:de:94:b0:00:e8:31:84:2a:8c: - 03:e4:c9:f1:b0:4f:42:9c:08:f1:a6:17:18:35:0d:18:0d:a9: - a7:1b:81:41:3a:b4:2d:f3:ef:0f:4c:4e:48:a7:f6:6f:94:f3: - d6:e7:ae:1a ------BEGIN CERTIFICATE----- -MIIEoTCCA4mgAwIBAgIBCjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTIzMzEwWhcNMTkwMjE1MTIzMzEwWjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBRnmp/CQWkn+xdvqTPVZJ -oT/bCGaxPcWtakpF6/Ff5y2alhsvBZdXJ90t7l2MrL6b8C4mXxghIrVB86Zli26E -k9/v5C2ozdX/VTwfnSx3Qz+0yEwYJVs5n7HplZrWWqcHYNaLzRdrhphnhkVJ3/Xq -KX5244K/4CcpyMyCIrqObXOxiwPVKhlpxZd71sz8kL8PLk/sqyYOAcb18lRUTnRU -NLzeFF0t1ACh3IiE2EALGhfLeyKKrT2smw1kfVFkElB2279qRIe1MwgoxI+IJLHC -qbrnWOfNmcDDBRxKMfxz33FBrgnoajFpKXus/kj8agrwbNyOJBBrSKWjr+5D0Y6t -AgMBAAGjggF4MIIBdDAdBgNVHQ4EFgQUIoVXrI3J51BmuLr/+7wVeDRS8owwHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwbAYDVR0RBGUwY4IJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEAAAA -AIcECgECD4cECgECEIcECgECEYcECgECEocECgECE4cECgECFIcECgECFYcECgEC -FjANBgkqhkiG9w0BAQsFAAOCAQEAUveUFkQqwuPvtJGTYRnS80a4j16JHDfV8I07 -6zBHwtml/cFIF7keitOnLQZD5TlCMpzxqUfxJHvar66X47uMmLAzh/M7QyKZ9UK2 -H2ID5xb2YbrWtwooPRlu19zIfvILl0Ya2JVxjdoiRdaJ6EvmnctfkoAmo6ls/HyA -/uPtjPadd00GNGmVlb3+8F5Xju6FZVfXyRh3nFjD5OukBxHwQWGvTEAk0wMBiYVZ -CWB27K7iU8+PvqkPxZmlOjrfcyJJ9dnaQ0io1TiVdwA8Hi2G3pSwAOgxhCqMA+TJ -8bBPQpwI8aYXGDUNGA2ppxuBQTq0LfPvD0xOSKf2b5Tz1ueuGg== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/0B.pem b/camel-ids/ssl/certs/0B.pem deleted file mode 100644 index 592c2115c..000000000 --- a/camel-ids/ssl/certs/0B.pem +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 11 (0xb) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 12:33:19 2017 GMT - Not After : Feb 15 12:33:19 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:af:7a:37:24:3f:d1:60:a2:b1:d5:f2:3c:97:4a: - 9a:4f:c4:05:07:f9:ac:60:52:37:41:76:9d:56:ee: - e0:b5:e3:87:2b:21:f5:65:8e:d7:db:8e:38:95:5a: - 5a:18:df:6f:56:b4:f3:77:5b:e2:dc:6a:be:fe:3b: - 4f:17:d3:c9:f1:44:7e:68:5d:a6:5a:f8:ff:de:1e: - 22:60:3a:73:9b:e7:c2:14:42:1b:72:57:9e:f7:83: - e8:a2:ef:6b:85:5e:57:de:64:0a:ed:2d:f7:b0:1f: - 45:f3:4d:25:61:1e:e1:40:4f:a5:31:8a:a7:9a:fa: - 5b:44:d6:dc:29:95:e6:94:64:42:82:a7:af:15:61: - 0d:dc:7e:64:90:35:ef:7d:4c:ba:ed:d4:a7:55:68: - 61:80:e4:ae:14:ee:e6:a3:08:3f:0a:90:d5:06:a0: - cf:10:13:b5:fe:09:5b:fc:e7:59:ce:6a:d0:25:79: - 64:6c:14:5f:5d:8f:6f:58:b0:86:bb:29:86:f9:eb: - 86:80:d7:6e:46:96:b0:61:60:71:a6:00:35:bd:89: - b4:58:e4:49:94:69:a2:06:36:c7:c9:b5:ac:da:62: - 51:21:98:c2:56:53:b2:50:62:af:83:4d:62:9b:c6: - 50:27:16:d9:30:8f:b8:39:d2:13:cd:e7:04:cf:9b: - 5b:63 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - B1:09:6F:20:2F:F3:A9:2E:F0:93:63:C9:40:12:18:33:99:A6:05:6E - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:0.0.0.0, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19, IP Address:10.1.2.20, IP Address:10.1.2.21, IP Address:10.1.2.22 - Signature Algorithm: sha256WithRSAEncryption - 68:b4:77:f9:27:59:44:34:e2:f4:ef:d1:72:59:4e:6e:1b:23: - 60:41:f7:c6:32:38:13:94:98:48:ac:f0:f9:d5:f2:dc:54:ad: - 5e:b0:de:ad:85:20:b3:86:f5:d2:7c:b1:85:2e:db:f0:fb:88: - b8:37:71:d0:f3:be:1b:73:e0:b0:9b:e0:b7:6c:46:e7:9a:fd: - a6:ca:07:f1:05:d7:7f:6a:d2:6b:46:e5:52:ad:06:7b:39:6d: - a8:a1:f9:d8:f0:7b:4f:3b:96:12:1f:41:fd:38:e7:a2:fd:29: - 8e:d4:66:4a:0e:24:8f:60:d3:0a:3f:55:5f:a8:98:3d:85:bd: - 9e:bb:d3:33:a0:26:99:2c:22:eb:77:d4:e1:e0:fc:81:a6:1f: - 39:be:96:72:ad:c1:72:c5:61:e7:8d:30:de:c8:09:41:c0:a7: - 67:ca:12:05:b3:45:a0:23:b5:bb:ad:41:f6:86:7e:dd:b5:be: - cc:6f:65:69:e0:ba:39:6d:bd:27:63:9a:eb:7a:9a:1b:91:a3: - 8d:fb:6e:9c:64:eb:08:46:a6:7e:b3:97:93:f9:aa:91:9a:a5: - 53:90:92:44:e0:67:c7:e7:f0:7f:6c:d0:59:e7:bf:21:91:13: - e7:b4:6b:ae:d4:84:33:2a:e4:df:76:1a:56:96:29:26:f7:a8: - 6d:ef:55:93 ------BEGIN CERTIFICATE----- -MIIEoTCCA4mgAwIBAgIBCzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTIzMzE5WhcNMTkwMjE1MTIzMzE5WjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvejckP9FgorHV8jyXSppP -xAUH+axgUjdBdp1W7uC144crIfVljtfbjjiVWloY329WtPN3W+Lcar7+O08X08nx -RH5oXaZa+P/eHiJgOnOb58IUQhtyV573g+ii72uFXlfeZArtLfewH0XzTSVhHuFA -T6Uxiqea+ltE1twpleaUZEKCp68VYQ3cfmSQNe99TLrt1KdVaGGA5K4U7uajCD8K -kNUGoM8QE7X+CVv851nOatAleWRsFF9dj29YsIa7KYb564aA125GlrBhYHGmADW9 -ibRY5EmUaaIGNsfJtazaYlEhmMJWU7JQYq+DTWKbxlAnFtkwj7g50hPN5wTPm1tj -AgMBAAGjggF4MIIBdDAdBgNVHQ4EFgQUsQlvIC/zqS7wk2PJQBIYM5mmBW4wHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwbAYDVR0RBGUwY4IJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEAAAA -AIcECgECD4cECgECEIcECgECEYcECgECEocECgECE4cECgECFIcECgECFYcECgEC -FjANBgkqhkiG9w0BAQsFAAOCAQEAaLR3+SdZRDTi9O/RcllObhsjYEH3xjI4E5SY -SKzw+dXy3FStXrDerYUgs4b10nyxhS7b8PuIuDdx0PO+G3PgsJvgt2xG55r9psoH -8QXXf2rSa0blUq0GezltqKH52PB7TzuWEh9B/Tjnov0pjtRmSg4kj2DTCj9VX6iY -PYW9nrvTM6AmmSwi63fU4eD8gaYfOb6Wcq3BcsVh540w3sgJQcCnZ8oSBbNFoCO1 -u61B9oZ+3bW+zG9laeC6OW29J2Oa63qaG5GjjftunGTrCEamfrOXk/mqkZqlU5CS -ROBnx+fwf2zQWee/IZET57RrrtSEMyrk33YaVpYpJveobe9Vkw== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/client.cert b/camel-ids/ssl/certs/client.cert deleted file mode 100644 index 8e5e59f82..000000000 --- a/camel-ids/ssl/certs/client.cert +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 10 (0xa) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 12:33:10 2017 GMT - Not After : Feb 15 12:33:10 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c1:46:79:a9:fc:24:16:92:7f:b1:76:fa:93:3d: - 56:49:a1:3f:db:08:66:b1:3d:c5:ad:6a:4a:45:eb: - f1:5f:e7:2d:9a:96:1b:2f:05:97:57:27:dd:2d:ee: - 5d:8c:ac:be:9b:f0:2e:26:5f:18:21:22:b5:41:f3: - a6:65:8b:6e:84:93:df:ef:e4:2d:a8:cd:d5:ff:55: - 3c:1f:9d:2c:77:43:3f:b4:c8:4c:18:25:5b:39:9f: - b1:e9:95:9a:d6:5a:a7:07:60:d6:8b:cd:17:6b:86: - 98:67:86:45:49:df:f5:ea:29:7e:76:e3:82:bf:e0: - 27:29:c8:cc:82:22:ba:8e:6d:73:b1:8b:03:d5:2a: - 19:69:c5:97:7b:d6:cc:fc:90:bf:0f:2e:4f:ec:ab: - 26:0e:01:c6:f5:f2:54:54:4e:74:54:34:bc:de:14: - 5d:2d:d4:00:a1:dc:88:84:d8:40:0b:1a:17:cb:7b: - 22:8a:ad:3d:ac:9b:0d:64:7d:51:64:12:50:76:db: - bf:6a:44:87:b5:33:08:28:c4:8f:88:24:b1:c2:a9: - ba:e7:58:e7:cd:99:c0:c3:05:1c:4a:31:fc:73:df: - 71:41:ae:09:e8:6a:31:69:29:7b:ac:fe:48:fc:6a: - 0a:f0:6c:dc:8e:24:10:6b:48:a5:a3:af:ee:43:d1: - 8e:ad - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 22:85:57:AC:8D:C9:E7:50:66:B8:BA:FF:FB:BC:15:78:34:52:F2:8C - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:0.0.0.0, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19, IP Address:10.1.2.20, IP Address:10.1.2.21, IP Address:10.1.2.22 - Signature Algorithm: sha256WithRSAEncryption - 52:f7:94:16:44:2a:c2:e3:ef:b4:91:93:61:19:d2:f3:46:b8: - 8f:5e:89:1c:37:d5:f0:8d:3b:eb:30:47:c2:d9:a5:fd:c1:48: - 17:b9:1e:8a:d3:a7:2d:06:43:e5:39:42:32:9c:f1:a9:47:f1: - 24:7b:da:af:ae:97:e3:bb:8c:98:b0:33:87:f3:3b:43:22:99: - f5:42:b6:1f:62:03:e7:16:f6:61:ba:d6:b7:0a:28:3d:19:6e: - d7:dc:c8:7e:f2:0b:97:46:1a:d8:95:71:8d:da:22:45:d6:89: - e8:4b:e6:9d:cb:5f:92:80:26:a3:a9:6c:fc:7c:80:fe:e3:ed: - 8c:f6:9d:77:4d:06:34:69:95:95:bd:fe:f0:5e:57:8e:ee:85: - 65:57:d7:c9:18:77:9c:58:c3:e4:eb:a4:07:11:f0:41:61:af: - 4c:40:24:d3:03:01:89:85:59:09:60:76:ec:ae:e2:53:cf:8f: - be:a9:0f:c5:99:a5:3a:3a:df:73:22:49:f5:d9:da:43:48:a8: - d5:38:95:77:00:3c:1e:2d:86:de:94:b0:00:e8:31:84:2a:8c: - 03:e4:c9:f1:b0:4f:42:9c:08:f1:a6:17:18:35:0d:18:0d:a9: - a7:1b:81:41:3a:b4:2d:f3:ef:0f:4c:4e:48:a7:f6:6f:94:f3: - d6:e7:ae:1a ------BEGIN CERTIFICATE----- -MIIEoTCCA4mgAwIBAgIBCjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTIzMzEwWhcNMTkwMjE1MTIzMzEwWjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBRnmp/CQWkn+xdvqTPVZJ -oT/bCGaxPcWtakpF6/Ff5y2alhsvBZdXJ90t7l2MrL6b8C4mXxghIrVB86Zli26E -k9/v5C2ozdX/VTwfnSx3Qz+0yEwYJVs5n7HplZrWWqcHYNaLzRdrhphnhkVJ3/Xq -KX5244K/4CcpyMyCIrqObXOxiwPVKhlpxZd71sz8kL8PLk/sqyYOAcb18lRUTnRU -NLzeFF0t1ACh3IiE2EALGhfLeyKKrT2smw1kfVFkElB2279qRIe1MwgoxI+IJLHC -qbrnWOfNmcDDBRxKMfxz33FBrgnoajFpKXus/kj8agrwbNyOJBBrSKWjr+5D0Y6t -AgMBAAGjggF4MIIBdDAdBgNVHQ4EFgQUIoVXrI3J51BmuLr/+7wVeDRS8owwHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwbAYDVR0RBGUwY4IJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEAAAA -AIcECgECD4cECgECEIcECgECEYcECgECEocECgECE4cECgECFIcECgECFYcECgEC -FjANBgkqhkiG9w0BAQsFAAOCAQEAUveUFkQqwuPvtJGTYRnS80a4j16JHDfV8I07 -6zBHwtml/cFIF7keitOnLQZD5TlCMpzxqUfxJHvar66X47uMmLAzh/M7QyKZ9UK2 -H2ID5xb2YbrWtwooPRlu19zIfvILl0Ya2JVxjdoiRdaJ6EvmnctfkoAmo6ls/HyA -/uPtjPadd00GNGmVlb3+8F5Xju6FZVfXyRh3nFjD5OukBxHwQWGvTEAk0wMBiYVZ -CWB27K7iU8+PvqkPxZmlOjrfcyJJ9dnaQ0io1TiVdwA8Hi2G3pSwAOgxhCqMA+TJ -8bBPQpwI8aYXGDUNGA2ppxuBQTq0LfPvD0xOSKf2b5Tz1ueuGg== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/client.key b/camel-ids/ssl/certs/client.key deleted file mode 100644 index 999e51f1b..000000000 --- a/camel-ids/ssl/certs/client.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBRnmp/CQWkn+x -dvqTPVZJoT/bCGaxPcWtakpF6/Ff5y2alhsvBZdXJ90t7l2MrL6b8C4mXxghIrVB -86Zli26Ek9/v5C2ozdX/VTwfnSx3Qz+0yEwYJVs5n7HplZrWWqcHYNaLzRdrhphn -hkVJ3/XqKX5244K/4CcpyMyCIrqObXOxiwPVKhlpxZd71sz8kL8PLk/sqyYOAcb1 -8lRUTnRUNLzeFF0t1ACh3IiE2EALGhfLeyKKrT2smw1kfVFkElB2279qRIe1Mwgo -xI+IJLHCqbrnWOfNmcDDBRxKMfxz33FBrgnoajFpKXus/kj8agrwbNyOJBBrSKWj -r+5D0Y6tAgMBAAECggEBAKRADz79b3HbWDdpxHMCymTSa2DqF9OCio7gaHRZmgyF -e0UHUdy5JK9FynqxOsFFQMtm5uFnKStnwqBkvsFHKEn1HXdR89ej7bwLJIg9Wz+T -X/1zxu8yN/+Vjm3S3P5TleT4T/wI9GFFxhkci5/He8ZfMwE4QbJsfPvOkLX7a42D -S37iaUjsmoCRz76awkOov0wZCnJqEQATXVFgTB2jOc7052j9eY+tk8/H6ayQndTh -vj6qcS5Y1Rd8qaWPkbE77HSPGz32Di9fN/jZ8TIGVjg7RunmlnOP0IX0YFuYflni -K6eEzEemtcnR3FOx9XB/fZmaUXV7BNGJKxriF1Fg6YECgYEA/PISxaMOgq5YSrlY -O4Vif00sgdOHLPINCqEz015aWAI7XkqeDhsHWu5rnXZtDjhlkGK5MdQ/dkT01ECn -p/bg1ZqGKaw7Bzbo4w6eQhOUm2I+5pUcL6APILt+DbHQGNzR/yf791XaMVoN1/uQ -TM493W2K+9BGbLvLU7iUFSANWk0CgYEAw5vxrkPg0jDxepgAnKkd2C+7dVMaqdCh -0EycNRBzWjqoVjJ5A39omTE71zrF9F22n9U7H0Q9JEi9Pd5j6EsTVBw7VLKNxOHS -/T7zBQUSvHQS96KSZVlUrj4je36pSBJTxz8mbHotpc9DxBA8JkzdDJmjyeE5Y1Ud -KxGgUT0QdeECgYAhGolMZk+i2LBjbyhV+dnvMSlvAEEDp9X/GyPOON34AKrGZ1uS -GwV2aBebbwFMyCK6p8D2/YEkuFeWY7PNbqj0K5n9YDYFdrE57hLWMPvU7iGvSbp7 -nSX9sawInMnQRy4Qh6oZL5oztUZ0is7SzncYQJrc4+AjoNw2Y8S1kxFMTQKBgHI9 -ajmvdObtJKrHiVv1PPPcdKvBvEm/CjH//B7Vm7jvlw64bYqIZ4tIgL1jmubrsFPK -kbvh+59sR/GRJ2IsLn6p+lCt8zQv+yxiDkY5P0cGt2ke7kb4lAcrTUe7opvv8DPm -gsdJ180FrnscTDTGITdRp6Gowv5rYByeL7YiZrGhAoGBAOkPVp0AXX6y6HO8TmIm -BAAyZ/w5mLoY2qzUou10Q5Na2ulX1uDcp4TvIDQA4Y0s7x5Yyo2tC74PA0LJg2qw -gM8vpDTXc9tk/42H/AYG4C3N9bseq9SfXayMT0bL/OkMWniImU+ZyZVZNhRHeQkl -PIZaz4luZ2d9LjtsZxMtbckD ------END PRIVATE KEY----- diff --git a/camel-ids/ssl/certs/client.p12 b/camel-ids/ssl/certs/client.p12 deleted file mode 100644 index 55ffc0f96..000000000 Binary files a/camel-ids/ssl/certs/client.p12 and /dev/null differ diff --git a/camel-ids/ssl/certs/server.cert b/camel-ids/ssl/certs/server.cert deleted file mode 100644 index 592c2115c..000000000 --- a/camel-ids/ssl/certs/server.cert +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 11 (0xb) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 12:33:19 2017 GMT - Not After : Feb 15 12:33:19 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:af:7a:37:24:3f:d1:60:a2:b1:d5:f2:3c:97:4a: - 9a:4f:c4:05:07:f9:ac:60:52:37:41:76:9d:56:ee: - e0:b5:e3:87:2b:21:f5:65:8e:d7:db:8e:38:95:5a: - 5a:18:df:6f:56:b4:f3:77:5b:e2:dc:6a:be:fe:3b: - 4f:17:d3:c9:f1:44:7e:68:5d:a6:5a:f8:ff:de:1e: - 22:60:3a:73:9b:e7:c2:14:42:1b:72:57:9e:f7:83: - e8:a2:ef:6b:85:5e:57:de:64:0a:ed:2d:f7:b0:1f: - 45:f3:4d:25:61:1e:e1:40:4f:a5:31:8a:a7:9a:fa: - 5b:44:d6:dc:29:95:e6:94:64:42:82:a7:af:15:61: - 0d:dc:7e:64:90:35:ef:7d:4c:ba:ed:d4:a7:55:68: - 61:80:e4:ae:14:ee:e6:a3:08:3f:0a:90:d5:06:a0: - cf:10:13:b5:fe:09:5b:fc:e7:59:ce:6a:d0:25:79: - 64:6c:14:5f:5d:8f:6f:58:b0:86:bb:29:86:f9:eb: - 86:80:d7:6e:46:96:b0:61:60:71:a6:00:35:bd:89: - b4:58:e4:49:94:69:a2:06:36:c7:c9:b5:ac:da:62: - 51:21:98:c2:56:53:b2:50:62:af:83:4d:62:9b:c6: - 50:27:16:d9:30:8f:b8:39:d2:13:cd:e7:04:cf:9b: - 5b:63 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - B1:09:6F:20:2F:F3:A9:2E:F0:93:63:C9:40:12:18:33:99:A6:05:6E - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:0.0.0.0, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19, IP Address:10.1.2.20, IP Address:10.1.2.21, IP Address:10.1.2.22 - Signature Algorithm: sha256WithRSAEncryption - 68:b4:77:f9:27:59:44:34:e2:f4:ef:d1:72:59:4e:6e:1b:23: - 60:41:f7:c6:32:38:13:94:98:48:ac:f0:f9:d5:f2:dc:54:ad: - 5e:b0:de:ad:85:20:b3:86:f5:d2:7c:b1:85:2e:db:f0:fb:88: - b8:37:71:d0:f3:be:1b:73:e0:b0:9b:e0:b7:6c:46:e7:9a:fd: - a6:ca:07:f1:05:d7:7f:6a:d2:6b:46:e5:52:ad:06:7b:39:6d: - a8:a1:f9:d8:f0:7b:4f:3b:96:12:1f:41:fd:38:e7:a2:fd:29: - 8e:d4:66:4a:0e:24:8f:60:d3:0a:3f:55:5f:a8:98:3d:85:bd: - 9e:bb:d3:33:a0:26:99:2c:22:eb:77:d4:e1:e0:fc:81:a6:1f: - 39:be:96:72:ad:c1:72:c5:61:e7:8d:30:de:c8:09:41:c0:a7: - 67:ca:12:05:b3:45:a0:23:b5:bb:ad:41:f6:86:7e:dd:b5:be: - cc:6f:65:69:e0:ba:39:6d:bd:27:63:9a:eb:7a:9a:1b:91:a3: - 8d:fb:6e:9c:64:eb:08:46:a6:7e:b3:97:93:f9:aa:91:9a:a5: - 53:90:92:44:e0:67:c7:e7:f0:7f:6c:d0:59:e7:bf:21:91:13: - e7:b4:6b:ae:d4:84:33:2a:e4:df:76:1a:56:96:29:26:f7:a8: - 6d:ef:55:93 ------BEGIN CERTIFICATE----- -MIIEoTCCA4mgAwIBAgIBCzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTIzMzE5WhcNMTkwMjE1MTIzMzE5WjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvejckP9FgorHV8jyXSppP -xAUH+axgUjdBdp1W7uC144crIfVljtfbjjiVWloY329WtPN3W+Lcar7+O08X08nx -RH5oXaZa+P/eHiJgOnOb58IUQhtyV573g+ii72uFXlfeZArtLfewH0XzTSVhHuFA -T6Uxiqea+ltE1twpleaUZEKCp68VYQ3cfmSQNe99TLrt1KdVaGGA5K4U7uajCD8K -kNUGoM8QE7X+CVv851nOatAleWRsFF9dj29YsIa7KYb564aA125GlrBhYHGmADW9 -ibRY5EmUaaIGNsfJtazaYlEhmMJWU7JQYq+DTWKbxlAnFtkwj7g50hPN5wTPm1tj -AgMBAAGjggF4MIIBdDAdBgNVHQ4EFgQUsQlvIC/zqS7wk2PJQBIYM5mmBW4wHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwbAYDVR0RBGUwY4IJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEAAAA -AIcECgECD4cECgECEIcECgECEYcECgECEocECgECE4cECgECFIcECgECFYcECgEC -FjANBgkqhkiG9w0BAQsFAAOCAQEAaLR3+SdZRDTi9O/RcllObhsjYEH3xjI4E5SY -SKzw+dXy3FStXrDerYUgs4b10nyxhS7b8PuIuDdx0PO+G3PgsJvgt2xG55r9psoH -8QXXf2rSa0blUq0GezltqKH52PB7TzuWEh9B/Tjnov0pjtRmSg4kj2DTCj9VX6iY -PYW9nrvTM6AmmSwi63fU4eD8gaYfOb6Wcq3BcsVh540w3sgJQcCnZ8oSBbNFoCO1 -u61B9oZ+3bW+zG9laeC6OW29J2Oa63qaG5GjjftunGTrCEamfrOXk/mqkZqlU5CS -ROBnx+fwf2zQWee/IZET57RrrtSEMyrk33YaVpYpJveobe9Vkw== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/server.key b/camel-ids/ssl/certs/server.key deleted file mode 100644 index 82f13b3b4..000000000 --- a/camel-ids/ssl/certs/server.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCvejckP9FgorHV -8jyXSppPxAUH+axgUjdBdp1W7uC144crIfVljtfbjjiVWloY329WtPN3W+Lcar7+ -O08X08nxRH5oXaZa+P/eHiJgOnOb58IUQhtyV573g+ii72uFXlfeZArtLfewH0Xz -TSVhHuFAT6Uxiqea+ltE1twpleaUZEKCp68VYQ3cfmSQNe99TLrt1KdVaGGA5K4U -7uajCD8KkNUGoM8QE7X+CVv851nOatAleWRsFF9dj29YsIa7KYb564aA125GlrBh -YHGmADW9ibRY5EmUaaIGNsfJtazaYlEhmMJWU7JQYq+DTWKbxlAnFtkwj7g50hPN -5wTPm1tjAgMBAAECggEAPO4O34NZTFixrzwhVdcNpczGgnJrLDbgANcS4vCnDgEn -Gg78insC8LV9aD6rMh/DJTRHpZY+O5LFJrmpSPi9Eg1aZxq9fLEhBxsnjIo/Qk9C -0I3zwcwy4nbm/Ext5S1RDWNnd9uSOZFiVIzhAcwbIp2FGqKud92ee1SvtbDbE4L5 -UKtiI4Gqiv29YPCQ2B3Q5LbH6ReeZCmbA6/lkJprgur00qdzbm9idRJ1EUtcUQMC -hMzqPzkSyjT2peskeXQ04d78BNxG9Ut09N9kUFQvF54hOMPorDF0Pc2zeB4ibec2 -5csSbca7Ajnx00M+o1BJJMYrem91sjwrfU36zfUdgQKBgQDda5VHkwVYtlIac72B -BjEcR2UDS3DO+uswujYkwWFiY3DHTpOEOf1OGREJkuEG1kyGYWZgdVhAhYi4057l -y0LelpSRJiYJkDNOKcxVUmR6691ytXd2Qz24AEfOHK2ZEHz+w4QAOINknIB841Og -kT9+nYZhimHqXXR9Dx2KQGl1sQKBgQDK4dR/uzG+0QgPoJDkFdW5h/mw6Pzu3S7S -qH4QfUJJoCrmu0ntfKSAxhcfTEaFDI40zGfN9puEut6b8BoEPlOqExuVU/CS/7Wp -ZunpHuijyB6LcwnPq8adwg2PdR/l7yL2Jyj12xyogAir4krTM7aDLpV1ngvIiCa3 -LExhRUMjUwKBgDzZ4zW/bvm5aYkBg/QgmoCWEmm8Yu1PQjGrC1RAnR3oDEeKDbqK -IVZER01lQ1iYroFD5VnfBfj9edyptAKdQOxhX8UgQdXg/midzh0ovpqVlc9/law3 -wI9/7Dv137OwN1ngq7dP0LRm2lz4MLRxFo0ah6Lo4A4Dzw7Lh6fGGfWRAoGAJi6m -PXvPeugAKmC/pA1v8cDjfyX6JEJAQ6kuQJAyX4TjThVFboqcsxeU1nEWfIfGY61s -g9i7oBlDN/nSC6ZnPIToFgx8JE43tDAIKbWFdv18siXuXMUpVhtlTfBvFmkRHV51 -WP/pvtSJzT+DcYgz+zBTNJWQBieJkcOmhE/yuL0CgYAdQMVz8QnfzC4WM4npxjbU -j6T8f86aTcmBFT7aKw6Vek9yj9DoJ0kyj3TreL2ds+G1zbpcetSlRzWGbe9zWmfB -U2yB45m731TNuIMXhJaCmYKbbc7FWYu6gJwXCPF16KcS4p8ytWkUeKATsntjHCOP -PI6dk3w5TIdCJG7JfYkYSg== ------END PRIVATE KEY----- diff --git a/camel-ids/ssl/certs/server.p12 b/camel-ids/ssl/certs/server.p12 deleted file mode 100644 index 2dfde3054..000000000 Binary files a/camel-ids/ssl/certs/server.p12 and /dev/null differ diff --git a/camel-ids/ssl/certs/test.cert b/camel-ids/ssl/certs/test.cert deleted file mode 100644 index b0b0f90af..000000000 --- a/camel-ids/ssl/certs/test.cert +++ /dev/null @@ -1,98 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 3 (0x3) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=DE, O=Fraunhofer, CN=IDS SubCA 2016 - Validity - Not Before: Feb 15 10:53:39 2017 GMT - Not After : Feb 15 10:53:39 2019 GMT - Subject: C=DE, ST=Bayern, L=Muenchen, O=Fraunhofer, OU=AISEC, CN=AISEC IDS Client - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c3:f9:1c:2b:cb:b5:40:da:a1:9d:04:20:64:77: - d2:f1:5a:ae:29:94:a0:6d:02:dc:92:be:c4:82:51: - a4:87:98:45:41:52:ee:aa:c0:af:8d:fe:13:03:20: - 63:e1:18:2d:b4:83:fd:d0:56:64:84:c3:3e:41:68: - 85:18:30:b5:9c:29:43:67:8b:70:6b:f2:0b:ee:2a: - cc:44:5b:98:7a:88:ae:cf:fc:5b:02:4d:15:57:06: - 63:1a:11:ab:99:81:61:e9:d5:ff:bd:04:c2:6c:ae: - c4:14:6b:a0:8a:88:f9:c8:54:ab:8f:56:49:1e:95: - cf:70:84:b6:b8:fb:fe:aa:f6:90:28:a0:e0:71:23: - 44:c3:a4:75:85:fb:c0:06:4e:cb:73:50:13:15:f6: - 7c:40:31:06:09:12:9d:ab:06:fa:ec:d0:6a:46:72: - 4f:2a:62:7b:bc:13:0d:29:d5:ce:88:27:98:25:25: - 5b:c0:41:57:49:b1:e3:95:e0:91:dc:8b:5f:9f:ae: - 34:77:e1:40:ec:92:03:d8:81:56:26:bf:f0:c1:ae: - 84:ba:7a:2a:0e:a5:b3:63:55:49:9c:dd:2d:2b:94: - 13:a8:05:ef:aa:79:5c:9e:18:d0:34:67:f8:f7:aa: - 79:e3:b9:83:ea:33:e7:08:94:5c:12:db:9b:bc:cc: - af:63 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 18:DE:0F:BE:24:E7:24:2C:92:F6:BB:35:21:E4:08:15:47:11:8A:0D - X509v3 Authority Key Identifier: - keyid:89:8B:82:EF:6B:2E:E4:40:2D:CE:5C:6C:F7:78:2E:7A:B0:7B:19:1D - - X509v3 Basic Constraints: - CA:FALSE - X509v3 Key Usage: - Digital Signature, Key Encipherment - X509v3 CRL Distribution Points: - - Full Name: - URI:http://crl.aisec.fraunhofer.de/ids.crl - - Authority Information Access: - CA Issuers - URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - - X509v3 Extended Key Usage: - TLS Web Client Authentication, TLS Web Server Authentication - X509v3 Subject Alternative Name: - DNS:localhost, DNS:idsconnector.aisec.fraunhofer.de, IP Address:127.0.0.1, IP Address:10.1.2.15, IP Address:10.1.2.16, IP Address:10.1.2.17, IP Address:10.1.2.18, IP Address:10.1.2.19 - Signature Algorithm: sha256WithRSAEncryption - 77:81:53:e3:26:5f:a1:c0:57:66:31:6b:5f:e9:80:26:a8:ae: - 8d:4a:1a:cd:5f:75:16:a6:01:d3:ac:53:f8:67:5a:40:7f:4e: - 3d:6a:32:a3:7e:73:58:4b:bb:d4:52:44:3b:91:f8:f6:28:3f: - db:85:61:ff:56:96:48:46:bd:24:58:44:c0:d1:19:fc:8a:b3: - b3:5e:a9:69:83:7a:b3:03:dc:79:bb:b7:58:67:92:48:ed:be: - d3:47:a6:c7:2c:85:56:5d:c2:88:2d:19:1a:17:29:e5:3c:9e: - 36:63:64:6b:7f:1e:c9:16:3b:4c:0b:e5:fd:6a:aa:6e:ab:96: - 22:75:86:2f:29:8d:93:d5:c5:ba:9f:6e:e8:10:09:2a:eb:5a: - 19:6e:49:c1:28:43:a6:25:87:22:70:bb:fc:0e:10:e0:5f:f7: - ab:35:80:c6:b4:73:b6:ca:d0:68:21:5c:b7:0a:35:c4:8f:63: - 22:2f:2b:51:24:36:24:77:80:e4:4f:a5:72:8a:2e:19:74:8e: - dd:c5:34:7b:85:2e:e4:f8:86:0f:73:95:d9:53:0b:be:f1:9c: - 37:f5:59:ab:1e:1a:2b:42:df:56:46:c8:28:7b:76:af:9a:25: - 66:1c:1b:17:b8:1c:3f:f5:93:69:bb:70:7f:81:c4:78:ce:f6: - 83:64:cb:63 ------BEGIN CERTIFICATE----- -MIIEjzCCA3egAwIBAgIBAzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJERTET -MBEGA1UECgwKRnJhdW5ob2ZlcjEXMBUGA1UEAwwOSURTIFN1YkNBIDIwMTYwHhcN -MTcwMjE1MTA1MzM5WhcNMTkwMjE1MTA1MzM5WjBxMQswCQYDVQQGEwJERTEPMA0G -A1UECAwGQmF5ZXJuMREwDwYDVQQHDAhNdWVuY2hlbjETMBEGA1UECgwKRnJhdW5o -b2ZlcjEOMAwGA1UECwwFQUlTRUMxGTAXBgNVBAMMEEFJU0VDIElEUyBDbGllbnQw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD+Rwry7VA2qGdBCBkd9Lx -Wq4plKBtAtySvsSCUaSHmEVBUu6qwK+N/hMDIGPhGC20g/3QVmSEwz5BaIUYMLWc -KUNni3Br8gvuKsxEW5h6iK7P/FsCTRVXBmMaEauZgWHp1f+9BMJsrsQUa6CKiPnI -VKuPVkkelc9whLa4+/6q9pAooOBxI0TDpHWF+8AGTstzUBMV9nxAMQYJEp2rBvrs -0GpGck8qYnu8Ew0p1c6IJ5glJVvAQVdJseOV4JHci1+frjR34UDskgPYgVYmv/DB -roS6eioOpbNjVUmc3S0rlBOoBe+qeVyeGNA0Z/j3qnnjuYPqM+cIlFwS25u8zK9j -AgMBAAGjggFmMIIBYjAdBgNVHQ4EFgQUGN4PviTnJCyS9rs1IeQIFUcRig0wHwYD -VR0jBBgwFoAUiYuC72su5EAtzlxs93guerB7GR0wCQYDVR0TBAIwADALBgNVHQ8E -BAMCBaAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5haXNlYy5mcmF1bmhv -ZmVyLmRlL2lkcy5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsGAQUFBzAChjhodHRw -Oi8vZG93bmxvYWRzLmFpc2VjLmZyYXVuaG9mZXIuZGUvcm9vdGNhY2VydDIwMTYu -Y2VydDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwWgYDVR0RBFMwUYIJ -bG9jYWxob3N0giBpZHNjb25uZWN0b3IuYWlzZWMuZnJhdW5ob2Zlci5kZYcEfwAA -AYcECgECD4cECgECEIcECgECEYcECgECEocECgECEzANBgkqhkiG9w0BAQsFAAOC -AQEAd4FT4yZfocBXZjFrX+mAJqiujUoazV91FqYB06xT+GdaQH9OPWoyo35zWEu7 -1FJEO5H49ig/24Vh/1aWSEa9JFhEwNEZ/Iqzs16paYN6swPcebu3WGeSSO2+00em -xyyFVl3CiC0ZGhcp5TyeNmNka38eyRY7TAvl/WqqbquWInWGLymNk9XFup9u6BAJ -KutaGW5JwShDpiWHInC7/A4Q4F/3qzWAxrRztsrQaCFctwo1xI9jIi8rUSQ2JHeA -5E+lcoouGXSO3cU0e4Uu5PiGD3OV2VMLvvGcN/VZqx4aK0LfVkbIKHt2r5olZhwb -F7gcP/WTabtwf4HEeM72g2TLYw== ------END CERTIFICATE----- diff --git a/camel-ids/ssl/certs/test.key b/camel-ids/ssl/certs/test.key deleted file mode 100644 index 77cbd19b6..000000000 --- a/camel-ids/ssl/certs/test.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDD+Rwry7VA2qGd -BCBkd9LxWq4plKBtAtySvsSCUaSHmEVBUu6qwK+N/hMDIGPhGC20g/3QVmSEwz5B -aIUYMLWcKUNni3Br8gvuKsxEW5h6iK7P/FsCTRVXBmMaEauZgWHp1f+9BMJsrsQU -a6CKiPnIVKuPVkkelc9whLa4+/6q9pAooOBxI0TDpHWF+8AGTstzUBMV9nxAMQYJ -Ep2rBvrs0GpGck8qYnu8Ew0p1c6IJ5glJVvAQVdJseOV4JHci1+frjR34UDskgPY -gVYmv/DBroS6eioOpbNjVUmc3S0rlBOoBe+qeVyeGNA0Z/j3qnnjuYPqM+cIlFwS -25u8zK9jAgMBAAECggEAGtQjsys0KSjFL0W9WYO98STE6xRZ0hKuN7i+FkkvCREj -ignceqveXMYHvEnW4p34w9m+CaOKJ1LDVxkD/4fLlRFhFO/V+DEuyPA6/rC7cyr7 -I6Ycn3gGD9/j+VGp+F3qFaUiWbIpG8/hMBp74/tUlsRgqELbx8AiofjJOxHkj2rs -AG6/SDQBhVPo9uZHmbOMtXwQzNOjBaz+L4GuZHk0K9tlwTzjMWNJwzSSdxT15sak -ojg4adoiTeZUdoCd1CdyfD8sVJlwjQpAGA36sB0Hym5uwnlZKStofoXPGWNjBPup -qS/wRKikrlBsu/pViIBbm4G1i25VgMSSxHjOHc24QQKBgQD/Gl8ZktSCHHMHNR/V -UTBePE50i/OUHuI0ZmIkYQNRxEadNEowf7Fk0AWgqTExeGTZz/L0n76KM1dnoiIV -upXHZrQQTcOpM/N9Rfj1bJzJuoQSeVfHa4sxiSK4uu2LOo9bA1PmpUjV5RGXPIvp -F1GlLakxzYrg3j5bTd50z7EvewKBgQDEqYNpTzSTIsIWAtBRbXe5T9189WXdQAJa -lKehoXObUWj/ulArCtXAHCZfC3HpFOGTgiQPpGA24zQuqRIFTGFf9ruUekzsyySZ -c+LOk8v1KtNxbfxGfRTAzG+Uq/6SheKiXPlw3TeQdCyvbTb7mAwEMb8HNVEAQY9P -mwALsCpHOQKBgQCjlxrDQJiMc4gEaDnoxu7Yj53UOWdTZlazObDYGWpShiauazjk -Tw7IUmo5dCZ6zfUGhMcNvl8nKvNzHtLy0jt4qtDv356IpCsR+8xCPotxBe3qFuyG -kt2pP4MHqb/pV/1UZRbpwrapjAMy0/341R5jaZult2TG/V5JmO7+Q64hfwKBgH4Y -hpbuXzJ8Vd/RHAsp2lsql0R5AEB1u0yjBjy/jaWn9GAL8T037EgKhJvqdbZSWjS/ -fCm/ZqWq1pmYdGKLT+A9DpcsN8iYlDYENQfpghwHwp13PQthRf481sqH4WnHiMI8 -RQAWB3uK0eAFcfytx/6keuy/RdmZL6+GHehgoysZAoGBAOVTl5ydUtN1M2I8u6dt -6Vbx6uxnay+fa1FoFceYeib5Y3NU8kj49jnObQHv4GU8651Ddo9ZuO4MtDSjgmt2 -ciezeY7TJZy0ovG8I+tnyNh6UQatxt1CqmxDnow+Zq4fkKJ5movdNXB1Pm190wtl -eFFRfOTTocGliFXUptaWGkhR ------END PRIVATE KEY----- diff --git a/camel-ids/ssl/certs/test.p12 b/camel-ids/ssl/certs/test.p12 deleted file mode 100644 index e69de29bb..000000000 diff --git a/camel-ids/ssl/client-keystore.jks b/camel-ids/ssl/client-keystore.jks deleted file mode 100644 index b892a543f..000000000 Binary files a/camel-ids/ssl/client-keystore.jks and /dev/null differ diff --git a/camel-ids/ssl/client-truststore.jks b/camel-ids/ssl/client-truststore.jks deleted file mode 100644 index 99ec32c12..000000000 Binary files a/camel-ids/ssl/client-truststore.jks and /dev/null differ diff --git a/camel-ids/ssl/configs/openssl-connector.cnf.template b/camel-ids/ssl/configs/openssl-connector.cnf.template deleted file mode 100755 index 89f3c97b9..000000000 --- a/camel-ids/ssl/configs/openssl-connector.cnf.template +++ /dev/null @@ -1,59 +0,0 @@ -HOME = . -RANDFILE = $ENV::HOME/.rnd - -#################################################################### -[ req ] -default_bits = 2048 -#default_keyfile = connector.key -distinguished_name = connector_distinguished_name -req_extensions = connector_req_extensions -string_mask = utf8only - -#################################################################### -[ connector_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = DE - -stateOrProvinceName = State or Province Name (full name) -stateOrProvinceName_default = Bayern - -localityName = Locality Name (eg, city) -localityName_default = Muenchen - -organizationName = Organization Name (eg, company) -organizationName_default = Fraunhofer - -organizationalUnitName = Organizational Unit Name (department, division) -organizationalUnitName_default = AISEC - -commonName = Common Name (e.g. server FQDN or YOUR name) -commonName_default = AISEC IDS Client - -emailAddress = Email Address -emailAddress_default = ids@aisec.fraunhofer.de - - -#################################################################### -[ connector_req_extensions ] - -subjectKeyIdentifier = hash -basicConstraints = CA:FALSE -keyUsage = digitalSignature, keyEncipherment, nonRepudiation -extendedKeyUsage = clientAuth, serverAuth -#securityProfile = ASN1:UTF8:IDS Security Profile Specification -#subjectAltName = URI:UUID:%%DEVICE_UUID%% -subjectAltName = @alternate_names - -[ alternate_names ] - -DNS.1 = localhost -DNS.2 = idsconnector.aisec.fraunhofer.de -IP.1 = 0.0.0.0 -IP.2 = 10.1.2.15 -IP.3 = 10.1.2.16 -IP.4 = 10.1.2.17 -IP.5 = 10.1.2.18 -IP.6 = 10.1.2.19 -IP.7 = 10.1.2.20 -IP.8 = 10.1.2.21 -IP.9 = 10.1.2.22 diff --git a/camel-ids/ssl/configs/openssl-connector.cnf.template.old b/camel-ids/ssl/configs/openssl-connector.cnf.template.old deleted file mode 100755 index b943510b6..000000000 --- a/camel-ids/ssl/configs/openssl-connector.cnf.template.old +++ /dev/null @@ -1,54 +0,0 @@ -HOME = . -RANDFILE = $ENV::HOME/.rnd - -#################################################################### -[ req ] -default_bits = 2048 -#default_keyfile = connector.key -distinguished_name = connector_distinguished_name -req_extensions = connector_req_extensions -string_mask = utf8only - -#################################################################### -[ connector_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = DE - -stateOrProvinceName = State or Province Name (full name) -stateOrProvinceName_default = Bayern - -localityName = Locality Name (eg, city) -localityName_default = Muenchen - -organizationName = Organization Name (eg, company) -organizationName_default = Fraunhofer - -organizationalUnitName = Organizational Unit Name (department, division) -organizationalUnitName_default = AISEC - -commonName = Common Name (e.g. server FQDN or YOUR name) -commonName_default = AISEC IDS Client - -emailAddress = Email Address -emailAddress_default = ids@aisec.fraunhofer.de - - -#################################################################### -[ connector_req_extensions ] - -subjectKeyIdentifier = hash -basicConstraints = CA:FALSE -keyUsage = digitalSignature, keyEncipherment, nonRepudiation -extendedKeyUsage = clientAuth -#securityProfile = ASN1:UTF8:IDS Security Profile Specification -#subjectAltName = URI:UUID:%%DEVICE_UUID%% -subjectAltName = @alternate_names - -[ alternate_names ] - -DNS.1 = localhost -DNS.2 = 127.0.0.1 -DNS.3 = idsconnector.aisec.fraunhofer.de - - - diff --git a/camel-ids/ssl/configs/openssl-rootca.cnf b/camel-ids/ssl/configs/openssl-rootca.cnf deleted file mode 100755 index c0c992025..000000000 --- a/camel-ids/ssl/configs/openssl-rootca.cnf +++ /dev/null @@ -1,74 +0,0 @@ -HOME = . -RANDFILE = $ENV::HOME/.rnd - -#################################################################### -[ ca ] -default_ca = CA_default # The default ca section - -[ CA_default ] - -default_days = 2920 # how long to certify for -default_md = sha256 # use public key default MD -preserve = no # keep passed DN ordering - -x509_extensions = ca_extensions # The extensions to add to the cert - -email_in_dn = no # Don't concat the email in the DN -copy_extensions = copy # Required to copy SANs from CSR to cert - -base_dir = ca -certificate = $base_dir/rootca.cert # The CA certifcate -private_key = $base_dir/rootca.key # The CA private key -new_certs_dir = certs # Location for new certs after signing -database = $base_dir/index.txt # Database index file -serial = $base_dir/serial.txt # The current serial number - -unique_subject = no # Set to 'no' to allow creation of - # several certificates with same subject. - -#################################################################### -[ req ] -default_bits = 2048 -default_keyfile = ca/rootca.key -distinguished_name = ca_distinguished_name -x509_extensions = ca_extensions -string_mask = utf8only - -#################################################################### -[ ca_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = DE - -organizationName = Organization Name (eg, company) -organizationName_default = Fraunhofer - -commonName = Common Name (e.g. server FQDN or YOUR name) -commonName_default = IDS Root CA 2016 - -#################################################################### -[ ca_extensions ] - -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid:always, issuer -basicConstraints = critical, CA:true -keyUsage = nonRepudiation, keyCertSign, cRLSign -#crlDistributionPoints=URI:http://crl.aisec.fraunhofer.de/ids.crl - -#################################################################### -[ signing_policy ] -countryName = optional -stateOrProvinceName = optional -localityName = optional -organizationName = optional -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -#################################################################### -[ signing_req_CA ] -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid -basicConstraints = critical, CA:true -keyUsage = digitalSignature, keyCertSign, cRLSign -crlDistributionPoints=URI:http://crl.aisec.fraunhofer.de/ids.crl -authorityInfoAccess=caIssuers;URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert diff --git a/camel-ids/ssl/configs/openssl-subca.cnf b/camel-ids/ssl/configs/openssl-subca.cnf deleted file mode 100755 index 344bd0a63..000000000 --- a/camel-ids/ssl/configs/openssl-subca.cnf +++ /dev/null @@ -1,76 +0,0 @@ -HOME = . -RANDFILE = $ENV::HOME/.rnd - -#################################################################### -[ ca ] -default_ca = CA_default # The default ca section - -[ CA_default ] - -default_days = 730 # how long to certify for -default_md = sha256 # use public key default MD -preserve = no # keep passed DN ordering - -x509_extensions = ca_extensions # The extensions to add to the cert - -email_in_dn = no # Don't concat the email in the DN -copy_extensions = copy # Required to copy SANs from CSR to cert - -base_dir = ca -certificate = $base_dir/subca.cert # The CA certifcate -private_key = $base_dir/subca.key # The CA private key -new_certs_dir = certs # Location for new certs after signing -database = $base_dir/index.txt # Database index file -serial = $base_dir/serial.txt # The current serial number - -unique_subject = no # Set to 'no' to allow creation of - # several certificates with same subject. - -#################################################################### -[ req ] -default_bits = 2048 -default_keyfile = ca/subca.key -distinguished_name = ca_distinguished_name -req_extensions = ca_extensions -string_mask = utf8only - -#################################################################### -[ ca_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = DE - -organizationName = Organization Name (eg, company) -organizationName_default = Fraunhofer - -commonName = Common Name (e.g. server FQDN or YOUR name) -commonName_default = IDS SubCA 2016 - -#################################################################### -[ ca_extensions ] - -subjectKeyIdentifier=hash -#authorityKeyIdentifier=keyid:always, issuer -basicConstraints = critical, CA:true -keyUsage = digitalSignature, keyCertSign, cRLSign -crlDistributionPoints=URI:http://crl.aisec.fraunhofer.de/ids.crl -authorityInfoAccess=caIssuers;URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert - -#################################################################### -[ signing_policy ] -countryName = optional -stateOrProvinceName = optional -localityName = optional -organizationName = optional -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -#################################################################### -[ signing_req ] -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid,issuer - -basicConstraints = CA:FALSE -keyUsage = digitalSignature, keyEncipherment -crlDistributionPoints=URI:http://crl.aisec.fraunhofer.de/ids.crl -authorityInfoAccess=caIssuers;URI:http://downloads.aisec.fraunhofer.de/rootcacert2016.cert diff --git a/camel-ids/ssl/keystore.sh b/camel-ids/ssl/keystore.sh deleted file mode 100755 index fd23f7fa9..000000000 --- a/camel-ids/ssl/keystore.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -# -# Imports CA chain and connector cert into karaf keystore. Execute in $(Karaf-dir)/etc/keystores/ -# Then, build karaf. The keystore is automatically deployed. -if [ $# -eq 1 ] ; then - echo "Two arguments supplied, which is good" -else - echo "Invalid number of arguments: $# (expected one)" - echo "Usage: $0 PKCS12_filename (WITHOUT file ending)" - exit 1 -fi - -#keytool -keystore $2_truststore -importcert -alias ca -file test_ca_certs/rootca.cert -#keytool -keystore $2_keystore -importcert -alias subca -file test_ca_certs/subca.cert -#keytool -keystore $1-truststore.jks -importcert -alias subca -file test_ca_certs/cachain.cert -noprompt -keytool -keystore $1-truststore.jks -importcert -alias ca -file ca/rootca.cert -keytool -keystore $1-truststore.jks -importcert -alias subca -file ca/subca.cert - -keytool -v -importkeystore -srckeystore certs/$1.p12 -srcstoretype PKCS12 -destkeystore $1-keystore.jks -deststoretype JKS - diff --git a/camel-ids/ssl/readme.md b/camel-ids/ssl/readme.md deleted file mode 100644 index 1a5c9febb..000000000 --- a/camel-ids/ssl/readme.md +++ /dev/null @@ -1,24 +0,0 @@ -This is a script collection for creating a very simple Root/Sub-CA for Industrial Dataspace Test Environments. -** This is not meant for real world scenarios. Certificates should be issued by a real CA and handled accordingly. ** - -To create the CA/Sub-CA: -``` -./ca.sh -``` - -To create a certificate for a device: -``` -./cert.sh "connector-name" -``` -Before creating a device certificate, make sure the configs/openssl-connector.cnf.template template file is adapted to the use case. Please change the DNS/IP Adresses needed to your setup. - - -To create a keystore and truststore: -``` -./keystore.sh "connector-name" -``` - - -Documentation is located at https://fraunhofer-aisec.github.io/trusted-iot-connector-documentation/ - -(C)) Fraunhofer AISEC 2018 diff --git a/camel-ids/ssl/server-keystore.jks b/camel-ids/ssl/server-keystore.jks deleted file mode 100644 index d7edc0692..000000000 Binary files a/camel-ids/ssl/server-keystore.jks and /dev/null differ diff --git a/camel-ids/ssl/server-truststore.jks b/camel-ids/ssl/server-truststore.jks deleted file mode 100644 index 24511f7b3..000000000 Binary files a/camel-ids/ssl/server-truststore.jks and /dev/null differ diff --git a/camel-ids/LICENSE.txt b/camel-idscp2-osgi/LICENSE.txt similarity index 100% rename from camel-ids/LICENSE.txt rename to camel-idscp2-osgi/LICENSE.txt diff --git a/camel-idscp2-osgi/README.md b/camel-idscp2-osgi/README.md new file mode 100644 index 000000000..2c92b5fc9 --- /dev/null +++ b/camel-idscp2-osgi/README.md @@ -0,0 +1 @@ +The _camel-idscp2_ module adds IDSCP2 support to the integrated Camel deployment. It creates a Camel Component to make IDSCP2 available for building Camel routes. IDSCP2 itself is contained in module _idscp2_. diff --git a/camel-idscp2-osgi/bnd.bnd b/camel-idscp2-osgi/bnd.bnd new file mode 100644 index 000000000..f5c097400 --- /dev/null +++ b/camel-idscp2-osgi/bnd.bnd @@ -0,0 +1,6 @@ +Bundle-Name: IDS :: Camel IDSCP2 Support for OSGi +Bundle-SymbolicName: de.fhg.aisec.ids.camel.idscp2.osgi +Bundle-Description: Camel IDSCP2 protocol support for OSGi +Export-Package: \ + de.fhg.aisec.ids.camel.idscp2.osgi +Import-Package: * \ No newline at end of file diff --git a/camel-idscp2-osgi/build.gradle.kts b/camel-idscp2-osgi/build.gradle.kts new file mode 100644 index 000000000..daa9bd266 --- /dev/null +++ b/camel-idscp2-osgi/build.gradle.kts @@ -0,0 +1,54 @@ +import org.gradle.plugins.ide.idea.model.IdeaModel + +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map + +description = "Camel IDSCP2 Component" +version = libraryVersions["idscp2"] ?: error("IDSCP2 version not specified") + +plugins { + id("com.github.gmazzo.buildconfig") version "2.0.2" +} + +apply(plugin = "idea") + +buildConfig { + sourceSets.getByName("main") { + packageName("de.fhg.aisec.ids.informationmodelmanager") + buildConfigField("String", "INFOMODEL_VERSION", + "\"${libraryVersions["infomodel"] ?: error("Infomodel version not available")}\"") + } +} + +configure { + module { + // mark as generated sources for IDEA + generatedSourceDirs.add(File("${buildDir}/generated/source/buildConfig/main/main")) + } +} + +dependencies { + providedByBundle(project(":ids-api")) { isTransitive = false } + + providedByBundle("de.fhg.aisec.ids", "camel-idscp2", libraryVersions["idscp2"]) { + exclude("de.fraunhofer.iais.eis.ids.infomodel", "java") + exclude("de.fraunhofer.iais.eis.ids", "infomodel-serializer") + exclude("org.jetbrains.kotlin", "*") + exclude("org.jetbrains.kotlinx", "kotlinx-coroutines-core") + } + + implementation("de.fraunhofer.iais.eis.ids.infomodel", "java", libraryVersions["infomodel"]) + implementation("de.fraunhofer.iais.eis.ids", "infomodel-serializer", libraryVersions["infomodel"]) + + osgiCore("org.osgi", "osgi.cmpn", libraryVersions["osgiCompendium"]) + + providedByFeature("org.apache.camel", "camel-core", libraryVersions["camel"]) + + providedByFeature("com.google.protobuf", "protobuf-java", libraryVersions["protobuf"]) + + providedByBundle("com.google.guava", "guava", libraryVersions["guava"]) + + testImplementation("junit", "junit", libraryVersions["junit4"]) + testImplementation("org.apache.camel", "camel-test", libraryVersions["camel"]) + testImplementation("org.mockito", "mockito-core", libraryVersions["mockito"]) +} diff --git a/camel-idscp2-osgi/src/main/kotlin/de/fhg/aisec/ids/camel/idscp2/osgi/Idscp2OsgiComponent.kt b/camel-idscp2-osgi/src/main/kotlin/de/fhg/aisec/ids/camel/idscp2/osgi/Idscp2OsgiComponent.kt new file mode 100644 index 000000000..bf40cb9c0 --- /dev/null +++ b/camel-idscp2-osgi/src/main/kotlin/de/fhg/aisec/ids/camel/idscp2/osgi/Idscp2OsgiComponent.kt @@ -0,0 +1,72 @@ +/*- + * ========================LICENSE_START================================= + * camel-idscp2-osgi + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.camel.idscp2.osgi + +import de.fhg.aisec.ids.api.idscp2.Idscp2UsageControlInterface +import de.fhg.aisec.ids.api.settings.Settings +import de.fhg.aisec.ids.camel.idscp2.UsageControlMaps +import de.fhg.aisec.ids.camel.idscp2.Utils +import de.fhg.aisec.ids.informationmodelmanager.BuildConfig +import java.net.URI +import org.apache.camel.Exchange +import org.osgi.service.component.annotations.Activate +import org.osgi.service.component.annotations.Component +import org.osgi.service.component.annotations.Reference +import org.osgi.service.component.annotations.ReferenceCardinality + +@Suppress("unused") +@Component +class Idscp2OsgiComponent : Idscp2UsageControlInterface { + @Reference(cardinality = ReferenceCardinality.MANDATORY) private lateinit var settings: Settings + + init { + Utils.connectorUrlProducer = { settings.connectorProfile.connectorUrl } + Utils.maintainerUrlProducer = { settings.connectorProfile.maintainerUrl } + Utils.dapsUrlProducer = { settings.connectorConfig.dapsUrl } + Utils.infomodelVersion = BuildConfig.INFOMODEL_VERSION + } + + @Activate + fun activate() { + instance = this + } + + fun setSettings(settings: Settings) { + this.settings = settings + } + + override fun getExchangeContract(exchange: Exchange) = + UsageControlMaps.getExchangeContract(exchange) + + override fun isProtected(exchange: Exchange) = UsageControlMaps.isProtected(exchange) + + override fun protectBody(exchange: Exchange, contractUri: URI) = + UsageControlMaps.protectBody(exchange, contractUri) + + override fun unprotectBody(exchange: Exchange) = UsageControlMaps.unprotectBody(exchange) + + companion object { + private lateinit var instance: Idscp2OsgiComponent + + fun setInstance(instance: Idscp2OsgiComponent) { + Companion.instance = instance + } + } +} diff --git a/camel-ids/src/main/resources/META-INF/services/org/apache/camel/component/idsclientplain b/camel-idscp2-osgi/src/main/resources/META-INF/services/org/apache/camel/component/idscp2client similarity index 92% rename from camel-ids/src/main/resources/META-INF/services/org/apache/camel/component/idsclientplain rename to camel-idscp2-osgi/src/main/resources/META-INF/services/org/apache/camel/component/idscp2client index 688c0cadd..f0e6faab9 100644 --- a/camel-ids/src/main/resources/META-INF/services/org/apache/camel/component/idsclientplain +++ b/camel-idscp2-osgi/src/main/resources/META-INF/services/org/apache/camel/component/idscp2client @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -class=de.fhg.aisec.ids.camel.ids.client.WsComponent +class=de.fhg.aisec.ids.camel.idscp2.client.Idscp2ClientComponent diff --git a/camel-ids/src/main/resources/META-INF/services/org/apache/camel/component/idsserver b/camel-idscp2-osgi/src/main/resources/META-INF/services/org/apache/camel/component/idscp2server similarity index 92% rename from camel-ids/src/main/resources/META-INF/services/org/apache/camel/component/idsserver rename to camel-idscp2-osgi/src/main/resources/META-INF/services/org/apache/camel/component/idscp2server index cb4c1b9f3..95abf4615 100644 --- a/camel-ids/src/main/resources/META-INF/services/org/apache/camel/component/idsserver +++ b/camel-idscp2-osgi/src/main/resources/META-INF/services/org/apache/camel/component/idscp2server @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -class=de.fhg.aisec.ids.camel.ids.server.WebsocketComponent +class=de.fhg.aisec.ids.camel.idscp2.server.Idscp2ServerComponent diff --git a/camel-influxdb/build.gradle b/camel-influxdb/build.gradle deleted file mode 100644 index bad570517..000000000 --- a/camel-influxdb/build.gradle +++ /dev/null @@ -1,4 +0,0 @@ -dependencies { - influxFeature group: 'org.influxdb', name: 'influxdb-java', version: libraryVersions.influxDB - influxFeature group: 'org.apache.camel', name: 'camel-influxdb', version: libraryVersions.camel -} diff --git a/camel-influxdb/build.gradle.kts b/camel-influxdb/build.gradle.kts new file mode 100644 index 000000000..f19712029 --- /dev/null +++ b/camel-influxdb/build.gradle.kts @@ -0,0 +1,9 @@ +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map + +dependencies { + val influxFeature by configurations + + influxFeature("org.influxdb", "influxdb-java", libraryVersions["influxDB"]) + influxFeature("org.apache.camel", "camel-influxdb", libraryVersions["camel"]) +} diff --git a/camel-multipart-processor/.gitignore b/camel-multipart-processor/.gitignore deleted file mode 100644 index f6a4b7789..000000000 --- a/camel-multipart-processor/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -bin/ -/build/ -/generated/ -/generated-sources/ -/target/ diff --git a/camel-multipart-processor/bnd.bnd b/camel-multipart-processor/bnd.bnd index 4ce378e8c..88bccc6ce 100644 --- a/camel-multipart-processor/bnd.bnd +++ b/camel-multipart-processor/bnd.bnd @@ -1,7 +1,4 @@ Bundle-Name: IDS :: Camel Multipart Processor Bundle-Description: Mime/Multipart support for Camel messages -Export-Package: \ - de.fhg.aisec.ids.camel.multipart -Import-Package: \ - !org.checkerframework.checker*,\ - * +Export-Package: de.fhg.aisec.ids.camel.multipart +Import-Package: * diff --git a/camel-multipart-processor/build.gradle b/camel-multipart-processor/build.gradle deleted file mode 100644 index d43d342c7..000000000 --- a/camel-multipart-processor/build.gradle +++ /dev/null @@ -1,26 +0,0 @@ -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - - // Bill of Materials (BOM) for Camel - bom group: 'org.apache.camel', name: 'camel-parent', version: libraryVersions.camel - - providedByFeature group: 'org.apache.camel', name: 'camel-core', version: libraryVersions.camel - providedByFeature group: 'org.apache.camel', name: 'camel-http4', version: libraryVersions.camelHttp4 - - compileOnly group: 'org.checkerframework', name: 'checker-qual', version: libraryVersions.checkerQual - - providedByBundle group: 'org.apache.httpcomponents', name: 'httpcore-osgi', version: libraryVersions.httpcore - providedByBundle group: 'org.apache.httpcomponents', name: 'httpclient-osgi', version: libraryVersions.httpclient - - providedByBundle group: 'commons-fileupload', name: 'commons-fileupload', version: libraryVersions.commonsFileUpload - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - osgiCore group: 'org.apache.felix', name: 'org.apache.felix.framework', version: libraryVersions.felixFramework - osgiCore group: 'org.osgi', name: 'osgi.cmpn', version: libraryVersions.osgiCompendium - - testImplementation group: 'junit', name: 'junit' - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito - testImplementation group: 'org.apache.camel', name: 'camel-test', version: libraryVersions.camel -} diff --git a/camel-multipart-processor/build.gradle.kts b/camel-multipart-processor/build.gradle.kts new file mode 100644 index 000000000..5b2eebf2c --- /dev/null +++ b/camel-multipart-processor/build.gradle.kts @@ -0,0 +1,21 @@ +dependencies { + @Suppress("UNCHECKED_CAST") val libraryVersions = + rootProject.extra.get("libraryVersions") as Map + + providedByBundle(project(":ids-api")) { isTransitive = false } + + providedByFeature("org.apache.camel", "camel-core", libraryVersions["camel"]) + providedByFeature("org.apache.camel", "camel-http4", libraryVersions["camelHttp4"]) + + providedByBundle("org.apache.httpcomponents", "httpcore-osgi", libraryVersions["httpcore"]) + providedByBundle("org.apache.httpcomponents", "httpclient-osgi", libraryVersions["httpclient"]) + + providedByBundle("commons-fileupload", "commons-fileupload", libraryVersions["commonsFileUpload"]) + + osgiCore("org.apache.felix", "org.apache.felix.framework", libraryVersions["felixFramework"]) + osgiCore("org.osgi", "osgi.cmpn", libraryVersions["osgiCompendium"]) + + testImplementation("junit", "junit", libraryVersions["junit4"]) + testImplementation("org.mockito", "mockito-core", libraryVersions["mockito"]) + testImplementation("org.apache.camel", "camel-test", libraryVersions["camel"]) +} diff --git a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartConstants.java b/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartConstants.java deleted file mode 100644 index 439bd75a4..000000000 --- a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartConstants.java +++ /dev/null @@ -1,28 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-multipart-processor - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.multipart; - -final class MultiPartConstants { - - private MultiPartConstants() {} - - static final String MULTIPART_HEADER = "header"; - static final String MULTIPART_PAYLOAD = "payload"; -} diff --git a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartInputProcessor.java b/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartInputProcessor.java deleted file mode 100644 index ee2d2241a..000000000 --- a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartInputProcessor.java +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-multipart-processor - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.multipart; - -import java.io.InputStream; -import org.apache.camel.Exchange; -import org.apache.camel.Processor; - -public class MultiPartInputProcessor implements Processor { - - @Override - public void process(Exchange exchange) throws Exception { - // Parse Multipart message - MultiPartStringParser parser = - new MultiPartStringParser(exchange.getIn().getBody(InputStream.class)); - // Parser JSON Header (should be an InfoModel object) - exchange.getIn().setHeader("idsMultipartHeader", parser.getHeader()); - // Remove current Content-Type header before setting the new one - exchange.getIn().removeHeader("Content-Type"); - // Copy Content-Type from payload part - exchange.getIn().setHeader("Content-Type", parser.getPayloadContentType()); - // Populate body with extracted payload - exchange.getIn().setBody(parser.getPayload()); - } -} diff --git a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartOutputProcessor.java b/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartOutputProcessor.java deleted file mode 100644 index 327983e79..000000000 --- a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartOutputProcessor.java +++ /dev/null @@ -1,154 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-multipart-processor - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.multipart; - -import de.fhg.aisec.ids.api.infomodel.InfoModel; -import org.apache.camel.Exchange; -import org.apache.camel.Processor; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.entity.mime.content.InputStreamBody; -import org.apache.http.entity.mime.content.StringBody; - -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.UUID; - -/** - * The MultiPartOutputProcessor will read the Exchange's header "ids" (if present) and the - * Exchange's body and emit a stream with a body that is a mime-multipart message with two parts of - * content-type application/json: a "header" part containing the "ids" header and a "payload" part - * containing the body. - * - *

The whole message is supposed to look like this: - * --msgpart - * Content-Type: application/json; charset=utf-8 - * Content-Disposition: form-data; name="header" - * - * { - * "@type" : "ids:ConnectorAvailableMessage", - * "id" : "http://industrialdataspace.org/connectorAvailableMessage/34d761cf-5ca4-4a77-a7f4-b14d8f75636a", - * "issued" : "2018-10-25T11:37:08.245Z", - * "modelVersion" : "1.0.1-SNAPSHOT", - * "issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b", - * "securityToken" : { - * "@type" : "ids:Token", - * "id" : "http://industrialdataspace.org/token/e43c08e1-157b-4207-94a8-754e53f48839", - * "tokenFormat" : "https://w3id.org/idsa/code/tokenformat/JWT", - * "tokenValue" : "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJEQVBTIERDIiwiYXVkIjoiSURTX0RDX0FTIiwic3ViIjoiREFQUyByZXNwb25zZSB0b2tlbiIsIm5hbWUiOiJEeW5hbWljIEF0dHJpYnV0ZXMgUHJvdmlzaW9uIFNlcnZpY2UgJ0RBUFMnIChlZGl0aW9uICdEZXZlbG9wZXJzIENvbW11bml0eScpIiwiZXhwIjoxNTQwMzkyMzU1MDI2LCJASURTIjp7IkBjb250ZXh0Ijp7IlNlY3VyaXR5UHJvZmlsZSI6Imh0dHBzOi8vc2NoZW1hLmluZHVzdHJpYWxkYXRhc3BhY2Uub3JnL3NlY3VyaXR5UHJvZmlsZS8iLCJEYXRhVXNhZ2VDb250cm9sIjoiaHR0cHM6Ly9zY2hlbWEuaW5kdXN0cmlhbGRhdGFzcGFjZS5vcmcvc2VjdXJpdHlQcm9maWxlL2RhdGFVc2FnZUNvbnRyb2xTdXBwb3J0In0sIkB0eXBlIjoicHJvZmlsZSIsInByb2ZpbGUiOnsiaWRzaWQiOiJodHRwOi8vd3d3Lm5pY29zLXJkLmNvbS9JRFMvQ29ubmVjdG9ycy9icm8tZGMiLCJAdHlwZSI6IlNlY3VyaXR5UHJvZmlsZSIsIlNlY3VyaXR5UHJvZmlsZSI6eyJpbnRlZ3JpdHlQcm90ZWN0aW9uQW5kVmVyaWZpY2F0aW9uU3VwcG9ydCI6Ik5PTkUiLCJhdXRoZW50aWNhdGlvblN1cHBvcnQiOiJOT05FIiwic2VydmljZUlzb2xhdGlvblN1cHBvcnQiOiJOT05FIiwiaW50ZWdyaXR5UHJvdGVjdGlvblNjb3BlIjoiTk9ORSIsImFwcEV4ZWN1dGlvblJlc291cmNlcyI6Ik5PTkUiLCJkYXRhVXNhZ2VDb250cm9sU3VwcG9ydCI6Ik5PTkUiLCJhdWRpdExvZ2dpbmciOiJOT05FIiwibG9jYWxEYXRhQ29uZmlkZW50aWFsaXR5IjoiTk9ORSJ9fX0sImlhdCI6MTU0MDM4ODc1NX0.3gEV3OB-Gf_Z4Hv6H5iQpC7OEoBvcEV887uOFjgC7jb1vBujT_qyVk3ETtZSEKUd2izChlE4MjskbhW-7I6dNvYfZz_6Hif9iH0dMsncPair5aph7vsPpH4V0AjiKXBqJrDqDGZeZxZuqcD6RmQjTvSDpVKj120xRbG_GgQg5jVJa427fkIS792vg078d7BlBfWUeYT3HBLE-fFNpQ6FIGA559O70TyXbxk-POkUWDE2cRm_fk-qvpTVDr79YYpPNuLc_0HgSzZJtXuT_Hn2hScrkYKCFJivsqI6f3Z1SvsGGIX5aTE_YSIEULScaRcq5M0u4ze1ynnnbtL4r59tig" - * } - * } - * --msgpart - * Content-Type: application/json - * Content-Disposition: form-data; name="payload" - * - * { - * "@type" : "ids:BaseConnector", - * "id" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b", - * "defaultHost" : { - * "@type" : "ids:Host", - * "id" : "http://industrialdataspace.org/host/73171c77-10d1-4e12-b04e-f696c467897e", - * "protocol" : "https://w3id.org/idsa/code/protocol/HTTP", - * "accessUrl" : "http://companyA.com/ids/connector" - * }, - * "curator" : "http://companyB.com/ids/participant", - * "maintainer" : "http://companyA.com/ids/participant", - * "securityProfile" : { - * "@type" : "ids:SecurityProfile", - * "id" : "http://industrialdataspace.org/securityProfile/75f722e4-4165-4d06-b296-2cdfef39dca9", - * "basedOn" : [ "PredefinedSecurityProfile", "https://w3id.org/idsa/core/Level0SecurityProfile" ] - * }, - * "inboundModelVersions" : [ "1.0.1-SNAPSHOT" ], - * "outboundModelVersion" : "1.0.1-SNAPSHOT", - * "catalog" : { - * "@type" : "ids:Catalog", - * "id" : "http://industrialdataspace.org/catalog/04b84cfd-b28c-4d22-b936-ee899900294a", - * "offers" : [ { - * "@type" : "ids:Resource", - * "id" : "http://industrialdataspace.org/resource/2e8ceebd-43f8-41c9-8225-a763fe83931a", - * "titles" : [ { - * "@value" : "Quarterly Business Report", - * "@language" : "en" - * } ], - * "descriptions" : [ { - * "@value" : "Dataset without retrieval interface and further description.", - * "@language" : "en" - * } ] - * } ] - * } - * } - * --msgpart-- - * - * - * @author Julian Schütte (julian.schuette@aisec.fraunhofer.de) - * @author Michael Lux (michael.lux@aisec.fraunhofer.de) - */ -public class MultiPartOutputProcessor implements Processor { - - @Override - public void process(Exchange exchange) throws Exception { - String boundary = UUID.randomUUID().toString(); - - MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); - multipartEntityBuilder.setMode(HttpMultipartMode.STRICT); - multipartEntityBuilder.setBoundary(boundary); - - // Get the IDS InfoModelManager and retrieve a JSON-LD-serialized self-description that - // will be sent as a multipart "header" - InfoModel infoModel = MultiPartComponent.getInfoModelManager(); - String rdfHeader = ""; - if (infoModel != null) { - rdfHeader = infoModel.getConnectorAsJsonLd(); - } - - // Use the self-description provided by the InfoModelManager as "header" - multipartEntityBuilder.addPart( - MultiPartConstants.MULTIPART_HEADER, - new StringBody(rdfHeader, ContentType.APPLICATION_JSON)); - - // Get the Exchange body and turn it into the second part named "payload" - final var contentTypeString = exchange.getIn().getHeader("Content-Type"); - if (contentTypeString != null) { - InputStream payload = exchange.getIn().getBody(InputStream.class); - if (payload != null) { - multipartEntityBuilder.addPart( - MultiPartConstants.MULTIPART_PAYLOAD, - new InputStreamBody( - payload, - ContentType.create(exchange.getIn().getHeader("Content-Type").toString().split(";")[0]))); - } - } else { - String payload = exchange.getIn().getBody(String.class); - if (payload != null) { - multipartEntityBuilder.addPart( - MultiPartConstants.MULTIPART_PAYLOAD, - new StringBody(payload, ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), StandardCharsets.UTF_8))); - } - } - - // Remove current Content-Type header before setting the new one - exchange.getIn().removeHeader("Content-Type"); - // Set Content-Type for multipart message - exchange.getIn().setHeader("Content-Type", "multipart/mixed; boundary=" + boundary); - // Using InputStream as source for the message body - exchange.getIn().setBody(multipartEntityBuilder.build().getContent()); - } -} diff --git a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartStringParser.java b/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartStringParser.java deleted file mode 100644 index 2c724725f..000000000 --- a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartStringParser.java +++ /dev/null @@ -1,106 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * camel-multipart-processor - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.multipart; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileUpload; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.UploadContext; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; - -import static de.fhg.aisec.ids.camel.multipart.MultiPartConstants.MULTIPART_HEADER; -import static de.fhg.aisec.ids.camel.multipart.MultiPartConstants.MULTIPART_PAYLOAD; - -public class MultiPartStringParser implements UploadContext { - - private final InputStream multipartInput; - private final String boundary; - private String header; - private InputStream payload; - private String payloadContentType; - - MultiPartStringParser(final InputStream multipartInput) throws FileUploadException, IOException { - this.multipartInput = multipartInput; - multipartInput.mark(10240); - try (BufferedReader reader = - new BufferedReader(new InputStreamReader(multipartInput, StandardCharsets.UTF_8))) { - String boundaryLine = reader.readLine(); - if (boundaryLine == null) { - throw new IOException("Message body appears to be empty, expected multipart boundary."); - } - this.boundary = boundaryLine.substring(2).trim(); - this.multipartInput.reset(); - for (FileItem i : new FileUpload(new DiskFileItemFactory()).parseRequest(this)) { - String fieldName = i.getFieldName(); - if (MULTIPART_HEADER.equals(fieldName)) { - header = i.getString(); - } else if (MULTIPART_PAYLOAD.equals(fieldName)) { - payload = i.getInputStream(); - payloadContentType = i.getContentType(); - } else { - throw new IOException("Unknown multipart field name detected: " + fieldName); - } - } - } - } - - @Override - public String getCharacterEncoding() { - return StandardCharsets.UTF_8.name(); - } - - @Override - public int getContentLength() { - return -1; - } - - @Override - public String getContentType() { - return "multipart/form-data, boundary=" + this.boundary; - } - - @Override - public InputStream getInputStream() { - return multipartInput; - } - - @Override - public long contentLength() { - return -1; - } - - public String getHeader() { - return header; - } - - public InputStream getPayload() { - return payload; - } - - public String getPayloadContentType() { - return payloadContentType; - } -} diff --git a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartComponent.java b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartComponent.kt similarity index 58% rename from camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartComponent.java rename to camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartComponent.kt index 2b86fa67d..598833d25 100644 --- a/camel-multipart-processor/src/main/java/de/fhg/aisec/ids/camel/multipart/MultiPartComponent.java +++ b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartComponent.kt @@ -17,37 +17,36 @@ * limitations under the License. * =========================LICENSE_END================================== */ -package de.fhg.aisec.ids.camel.multipart; +package de.fhg.aisec.ids.camel.multipart -import de.fhg.aisec.ids.api.infomodel.InfoModel; -import org.osgi.service.component.annotations.Activate; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Reference; -import org.osgi.service.component.annotations.ReferenceCardinality; +import de.fhg.aisec.ids.api.infomodel.InfoModel +import org.osgi.service.component.annotations.Activate +import org.osgi.service.component.annotations.Component +import org.osgi.service.component.annotations.Reference +import org.osgi.service.component.annotations.ReferenceCardinality /** * The only purpose of this OSGi component is to connect to the InfoModelManager. * - *

This is required for the MultiPartComponent to use a proper IDS self description in the - * multipart messages. + * This is required for the MultiPartComponent to use a proper IDS self description in the multipart + * messages. * * @author Julian Schütte (julian.schuette@aisec.fraunhofer.de) */ @Component(name = "ids-multipart-component") -public class MultiPartComponent { +class MultiPartComponent { + @Reference(cardinality = ReferenceCardinality.MANDATORY) + lateinit var infoModelManager: InfoModel - @Reference(cardinality = ReferenceCardinality.MANDATORY) - private InfoModel infoModel = null; + @Activate + fun activate() { + instance = this + } - private static MultiPartComponent instance; + companion object { + private lateinit var instance: MultiPartComponent - @Activate - @SuppressWarnings("squid:S2696") - protected void activate() { - instance = this; - } - - public static InfoModel getInfoModelManager() { - return instance.infoModel; - } + val infoModelManager + get() = instance.infoModelManager + } } diff --git a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketProducerConsumer.java b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartConstants.kt similarity index 79% rename from camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketProducerConsumer.java rename to camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartConstants.kt index 3ab783c63..f55dc24df 100644 --- a/camel-ids/src/main/java/de/fhg/aisec/ids/camel/ids/server/WebsocketProducerConsumer.java +++ b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartConstants.kt @@ -1,6 +1,6 @@ /*- * ========================LICENSE_START================================= - * camel-ids + * camel-multipart-processor * %% * Copyright (C) 2019 Fraunhofer AISEC * %% @@ -17,10 +17,9 @@ * limitations under the License. * =========================LICENSE_END================================== */ -package de.fhg.aisec.ids.camel.ids.server; +package de.fhg.aisec.ids.camel.multipart -public interface WebsocketProducerConsumer { - - /** Gets the endpoint */ - WebsocketEndpoint getEndpoint(); +internal object MultiPartConstants { + const val MULTIPART_HEADER = "header" + const val MULTIPART_PAYLOAD = "payload" } diff --git a/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartInputProcessor.kt b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartInputProcessor.kt new file mode 100644 index 000000000..3df70d2df --- /dev/null +++ b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartInputProcessor.kt @@ -0,0 +1,42 @@ +/*- + * ========================LICENSE_START================================= + * camel-multipart-processor + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.camel.multipart + +import java.io.InputStream +import org.apache.camel.Exchange +import org.apache.camel.Processor + +class MultiPartInputProcessor : Processor { + @Throws(Exception::class) + override fun process(exchange: Exchange) { + exchange.message.let { + // Parse Multipart message + val parser = MultiPartStringParser(it.getBody(InputStream::class.java)) + // Parser JSON Header (should be an InfoModel object) + it.setHeader("idsMultipartHeader", parser.header) + // Remove current Content-Type header before setting the new one + it.removeHeader("Content-Type") + // Copy Content-Type from payload part + it.setHeader("Content-Type", parser.payloadContentType) + // Populate body with extracted payload + it.body = parser.payload + } + } +} diff --git a/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartOutputProcessor.kt b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartOutputProcessor.kt new file mode 100644 index 000000000..494c34a49 --- /dev/null +++ b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartOutputProcessor.kt @@ -0,0 +1,131 @@ +/*- + * ========================LICENSE_START================================= + * camel-multipart-processor + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.camel.multipart + +import de.fhg.aisec.ids.api.infomodel.InfoModel +import java.io.InputStream +import java.nio.charset.StandardCharsets +import java.util.* +import org.apache.camel.Exchange +import org.apache.camel.Processor +import org.apache.http.entity.ContentType +import org.apache.http.entity.mime.HttpMultipartMode +import org.apache.http.entity.mime.MultipartEntityBuilder +import org.apache.http.entity.mime.content.InputStreamBody +import org.apache.http.entity.mime.content.StringBody + +/** + * The MultiPartOutputProcessor will read the Exchange's header "ids" (if present) and the + * Exchange's body and emit a stream with a body that is a mime-multipart message with two parts of + * content-type application/json: a "header" part containing the "ids" header and a "payload" part + * containing the body. + * + *

The whole message is supposed to look like this: --msgpart Content-Type: + * application/json; charset=utf-8 Content-Disposition: form-data; name="header" + * + * { "@type" : "ids:ConnectorAvailableMessage", "id" : + * "http://industrialdataspace.org/connectorAvailableMessage/34d761cf-5ca4-4a77-a7f4-b14d8f75636a", + * "issued" : "2018-10-25T11:37:08.245Z", "modelVersion" : "1.0.1-SNAPSHOT", "issuerConnector" : + * "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b", "securityToken" : { + * "@type" : "ids:Token", "id" : + * "http://industrialdataspace.org/token/e43c08e1-157b-4207-94a8-754e53f48839", "tokenFormat" : + * "https://w3id.org/idsa/code/tokenformat/JWT", "tokenValue" : + * "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJEQVBTIERDIiwiYXVkIjoiSURTX0RDX0FTIiwic3ViIjoiREFQUyByZXNwb25zZSB0b2tlbiIsIm5hbWUiOiJEeW5hbWljIEF0dHJpYnV0ZXMgUHJvdmlzaW9uIFNlcnZpY2UgJ0RBUFMnIChlZGl0aW9uICdEZXZlbG9wZXJzIENvbW11bml0eScpIiwiZXhwIjoxNTQwMzkyMzU1MDI2LCJASURTIjp7IkBjb250ZXh0Ijp7IlNlY3VyaXR5UHJvZmlsZSI6Imh0dHBzOi8vc2NoZW1hLmluZHVzdHJpYWxkYXRhc3BhY2Uub3JnL3NlY3VyaXR5UHJvZmlsZS8iLCJEYXRhVXNhZ2VDb250cm9sIjoiaHR0cHM6Ly9zY2hlbWEuaW5kdXN0cmlhbGRhdGFzcGFjZS5vcmcvc2VjdXJpdHlQcm9maWxlL2RhdGFVc2FnZUNvbnRyb2xTdXBwb3J0In0sIkB0eXBlIjoicHJvZmlsZSIsInByb2ZpbGUiOnsiaWRzaWQiOiJodHRwOi8vd3d3Lm5pY29zLXJkLmNvbS9JRFMvQ29ubmVjdG9ycy9icm8tZGMiLCJAdHlwZSI6IlNlY3VyaXR5UHJvZmlsZSIsIlNlY3VyaXR5UHJvZmlsZSI6eyJpbnRlZ3JpdHlQcm90ZWN0aW9uQW5kVmVyaWZpY2F0aW9uU3VwcG9ydCI6Ik5PTkUiLCJhdXRoZW50aWNhdGlvblN1cHBvcnQiOiJOT05FIiwic2VydmljZUlzb2xhdGlvblN1cHBvcnQiOiJOT05FIiwiaW50ZWdyaXR5UHJvdGVjdGlvblNjb3BlIjoiTk9ORSIsImFwcEV4ZWN1dGlvblJlc291cmNlcyI6Ik5PTkUiLCJkYXRhVXNhZ2VDb250cm9sU3VwcG9ydCI6Ik5PTkUiLCJhdWRpdExvZ2dpbmciOiJOT05FIiwibG9jYWxEYXRhQ29uZmlkZW50aWFsaXR5IjoiTk9ORSJ9fX0sImlhdCI6MTU0MDM4ODc1NX0.3gEV3OB-Gf_Z4Hv6H5iQpC7OEoBvcEV887uOFjgC7jb1vBujT_qyVk3ETtZSEKUd2izChlE4MjskbhW-7I6dNvYfZz_6Hif9iH0dMsncPair5aph7vsPpH4V0AjiKXBqJrDqDGZeZxZuqcD6RmQjTvSDpVKj120xRbG_GgQg5jVJa427fkIS792vg078d7BlBfWUeYT3HBLE-fFNpQ6FIGA559O70TyXbxk-POkUWDE2cRm_fk-qvpTVDr79YYpPNuLc_0HgSzZJtXuT_Hn2hScrkYKCFJivsqI6f3Z1SvsGGIX5aTE_YSIEULScaRcq5M0u4ze1ynnnbtL4r59tig" + * } } --msgpart Content-Type: application/json Content-Disposition: form-data; name="payload" + * + * { "@type" : "ids:BaseConnector", "id" : + * "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b", "defaultHost" : { "@type" + * : "ids:Host", "id" : "http://industrialdataspace.org/host/73171c77-10d1-4e12-b04e-f696c467897e", + * "protocol" : "https://w3id.org/idsa/code/protocol/HTTP", "accessUrl" : + * "http://companyA.com/ids/connector" }, "curator" : "http://companyB.com/ids/participant", + * "maintainer" : "http://companyA.com/ids/participant", "securityProfile" : { "@type" : + * "ids:SecurityProfile", "id" : + * "http://industrialdataspace.org/securityProfile/75f722e4-4165-4d06-b296-2cdfef39dca9", "basedOn" + * : [ "PredefinedSecurityProfile", "https://w3id.org/idsa/core/Level0SecurityProfile" ] }, + * "inboundModelVersions" : [ "1.0.1-SNAPSHOT" ], "outboundModelVersion" : "1.0.1-SNAPSHOT", + * "catalog" : { "@type" : "ids:Catalog", "id" : + * "http://industrialdataspace.org/catalog/04b84cfd-b28c-4d22-b936-ee899900294a", "offers" : [ { + * "@type" : "ids:Resource", "id" : + * "http://industrialdataspace.org/resource/2e8ceebd-43f8-41c9-8225-a763fe83931a", "titles" : [ { + * "@value" : "Quarterly Business Report", "@language" : "en" } ], "descriptions" : [ { "@value" : + * "Dataset without retrieval interface and further description.", "@language" : "en" } ] } ] } } + * --msgpart-- + * + * @author Julian Schütte (julian.schuette@aisec.fraunhofer.de) + * @author Michael Lux (michael.lux@aisec.fraunhofer.de) + */ +class MultiPartOutputProcessor : Processor { + @Throws(Exception::class) + override fun process(exchange: Exchange) { + val boundary = UUID.randomUUID().toString() + val multipartEntityBuilder = MultipartEntityBuilder.create() + multipartEntityBuilder.setMode(HttpMultipartMode.STRICT) + multipartEntityBuilder.setBoundary(boundary) + + // Get the IDS InfoModelManager and retrieve a JSON-LD-serialized self-description that + // will be sent as a multipart "header" + val infoModel: InfoModel = MultiPartComponent.infoModelManager + val rdfHeader = infoModel.connectorAsJsonLd + + // Use the self-description provided by the InfoModelManager as "header" + multipartEntityBuilder.addPart( + MultiPartConstants.MULTIPART_HEADER, + StringBody(rdfHeader, ContentType.APPLICATION_JSON) + ) + + exchange.message.let { + // Get the Exchange body and turn it into the second part named "payload" + val contentTypeString = it.getHeader("Content-Type") + if (contentTypeString != null) { + val payload = it.getBody(InputStream::class.java) + if (payload != null) { + multipartEntityBuilder.addPart( + MultiPartConstants.MULTIPART_PAYLOAD, + InputStreamBody( + payload, + ContentType.create(contentTypeString.toString().split(";").first()) + ) + ) + } + } else { + val payload = it.getBody(String::class.java) + if (payload != null) { + multipartEntityBuilder.addPart( + MultiPartConstants.MULTIPART_PAYLOAD, + StringBody( + payload, + ContentType.create( + ContentType.TEXT_PLAIN.mimeType, + StandardCharsets.UTF_8 + ) + ) + ) + } + } + + // Remove current Content-Type header before setting the new one + it.removeHeader("Content-Type") + // Set Content-Type for multipart message + it.setHeader("Content-Type", "multipart/mixed; boundary=$boundary") + // Using InputStream as source for the message body + it.body = multipartEntityBuilder.build().content + } + } +} diff --git a/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartStringParser.kt b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartStringParser.kt new file mode 100644 index 000000000..ad545312c --- /dev/null +++ b/camel-multipart-processor/src/main/kotlin/de/fhg/aisec/ids/camel/multipart/MultiPartStringParser.kt @@ -0,0 +1,85 @@ +/*- + * ========================LICENSE_START================================= + * camel-multipart-processor + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.camel.multipart + +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStream +import java.io.InputStreamReader +import java.nio.charset.StandardCharsets +import org.apache.commons.fileupload.FileUpload +import org.apache.commons.fileupload.UploadContext +import org.apache.commons.fileupload.disk.DiskFileItemFactory +import org.slf4j.LoggerFactory + +class MultiPartStringParser internal constructor(private val multipartInput: InputStream) : + UploadContext { + private var boundary: String? = null + var header: String? = null + var payload: InputStream? = null + var payloadContentType: String? = null + + override fun getCharacterEncoding(): String = StandardCharsets.UTF_8.name() + + override fun getContentLength() = -1 + + override fun getContentType() = "multipart/form-data, boundary=$boundary" + + override fun getInputStream() = multipartInput + + override fun contentLength() = -1L + + companion object { + private val LOG = LoggerFactory.getLogger(MultiPartStringParser::class.java) + } + + init { + multipartInput.mark(10240) + BufferedReader(InputStreamReader(multipartInput, StandardCharsets.UTF_8)).use { reader -> + val boundaryLine = + reader.readLine() + ?: throw IOException( + "Message body appears to be empty, expected multipart boundary." + ) + boundary = boundaryLine.substring(2).trim { it <= ' ' } + multipartInput.reset() + for (i in FileUpload(DiskFileItemFactory()).parseRequest(this)) { + val fieldName = i.fieldName + if (LOG.isTraceEnabled) { + LOG.trace("Found multipart field with name \"{}\"", fieldName) + } + if (MultiPartConstants.MULTIPART_HEADER == fieldName) { + header = i.string + if (LOG.isDebugEnabled) { + LOG.debug("Found header:\n{}", header) + } + } else if (MultiPartConstants.MULTIPART_PAYLOAD == fieldName) { + payload = i.inputStream + payloadContentType = i.contentType + if (LOG.isDebugEnabled) { + LOG.debug("Found body with Content-Type \"{}\"", payloadContentType) + } + } else { + throw IOException("Unknown multipart field name detected: $fieldName") + } + } + } + } +} diff --git a/cxf-jaxws-patch/build.gradle b/cxf-jaxws-patch/build.gradle deleted file mode 100644 index 355e19e79..000000000 --- a/cxf-jaxws-patch/build.gradle +++ /dev/null @@ -1,3 +0,0 @@ -dependencies { - implementation group: 'javax.xml.ws', name: 'jaxws-api', version: libraryVersions.jaxwsApi -} diff --git a/cxf-jaxws-patch/build.gradle.kts b/cxf-jaxws-patch/build.gradle.kts new file mode 100644 index 000000000..faa04f48b --- /dev/null +++ b/cxf-jaxws-patch/build.gradle.kts @@ -0,0 +1,6 @@ +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map + +dependencies { + implementation("javax.xml.ws", "jaxws-api", libraryVersions["jaxwsApi"]) +} diff --git a/docker-build/Dockerfile b/docker-build/Dockerfile index 549fbb8ca..94765b54f 100644 --- a/docker-build/Dockerfile +++ b/docker-build/Dockerfile @@ -1,21 +1,13 @@ -ARG JDK_BASE_IMAGE=fraunhoferaisec/jdk-base:develop -FROM $JDK_BASE_IMAGE +ARG BASE_IMAGE=adoptopenjdk:11-jdk-hotspot-focal +FROM $BASE_IMAGE LABEL AUTHOR="Michael Lux (michael.lux@aisec.fraunhofer.de)" -# Install tools for nodejs/yarn setup -RUN apt-get update -qq && apt-get install -qq bash sudo wget gnupg -# Install nodejs 12.x -RUN wget -O - https://deb.nodesource.com/setup_12.x | bash - && apt-get install -qq nodejs -# Install yarn -RUN wget -O - https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ - && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ - && apt-get update && apt-get install yarn -# Install protobuf compiler (protoc) -RUN apt-get update -qq && apt-get install -qq protobuf-compiler +# Install tools for nodejs/yarn setup and protobuf compiler +RUN apt-get update -qq && apt-get install -qq bash sudo wget gnupg protobuf-compiler COPY run.sh . RUN chmod +x run.sh ENTRYPOINT ["/run.sh"] -CMD ["build", "check", "--parallel"] \ No newline at end of file +CMD ["yarnBuild", "check", ":build", "--parallel"] \ No newline at end of file diff --git a/docker-build/run.sh b/docker-build/run.sh index 5d2a20c7f..1463c20e0 100644 --- a/docker-build/run.sh +++ b/docker-build/run.sh @@ -41,6 +41,9 @@ else addgroup --gid "$DOCKER_GID" --quiet docker # Create a build user with the UID of the /core-platfrom mount adduser --uid "$TARGET_UID" --disabled-password --ingroup docker --gecos 'Build User' --quiet build + # Fix ownerships for gradle and mvn + chown -R "$TARGET_UID:$TARGET_UID" "$GRADLE_DIR" "$M2_DIR" + # Create gradle/mvn symlinks in user directory ln -s "$GRADLE_DIR" /home/build/.gradle ln -s "$M2_DIR" /home/build/.m2 echo "Build parameters passed: $*" diff --git a/docker-jdk-base/Dockerfile b/docker-jdk-base/Dockerfile deleted file mode 100644 index a1dcadfc4..000000000 --- a/docker-jdk-base/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -ARG BASE_IMAGE -FROM $BASE_IMAGE - -LABEL AUTHOR="Michael Lux (michael.lux@aisec.fraunhofer.de)" \ No newline at end of file diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 000000000..ba475f688 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1 @@ +/log \ No newline at end of file diff --git a/examples/cert-stores/consumer-keystore.p12 b/examples/cert-stores/consumer-keystore.p12 index 6607767d6..f6c7368bc 100644 Binary files a/examples/cert-stores/consumer-keystore.p12 and b/examples/cert-stores/consumer-keystore.p12 differ diff --git a/examples/cert-stores/provider-keystore.p12 b/examples/cert-stores/provider-keystore.p12 index 830797f69..7c45bd308 100644 Binary files a/examples/cert-stores/provider-keystore.p12 and b/examples/cert-stores/provider-keystore.p12 differ diff --git a/examples/example-getting-started/docker-compose.yaml b/examples/example-getting-started/docker-compose.yaml index cda93372e..04b93c3e9 100644 --- a/examples/example-getting-started/docker-compose.yaml +++ b/examples/example-getting-started/docker-compose.yaml @@ -1,22 +1,6 @@ version: '3' services: - # TPM simulator - ids-tpmsim: - image: fraunhoferaisec/tpmsim:${EXAMPLE_TAG:-develop} - volumes: - - ../tpmsim/tpmsim_data.tar:/tpmsim_data.tar - networks: - - example-internal - - # Trusted third party (RAT repository) simulator - ids-ttpsim: - image: fraunhoferaisec/ttpsim:${EXAMPLE_TAG:-develop} - networks: - example-internal: - aliases: - - repository.aisec.fraunhofer.de - # The core platform, mounts docker control socket into the image ids-core: image: fraunhoferaisec/trusted-connector-core:${EXAMPLE_TAG:-develop} @@ -25,14 +9,10 @@ services: volumes: - ../log/:/root/log/ - /var/run/docker.sock:/var/run/docker.sock - - ./system.properties:/root/etc/system.properties - - ../tpmsim/rootCA.crt:/root/etc/rootca-cert.pem - ../cert-stores/consumer-keystore.p12:/root/etc/consumer-keystore.p12 - ../cert-stores/provider-keystore.p12:/root/etc/provider-keystore.p12 - ../cert-stores/truststore.p12:/root/etc/truststore.p12 - - ./example-idscp-localloop.xml:/root/deploy/example-idscp-localloop.xml - environment: - - TPM_HOST=ids-tpmsim + - ./example-idscp2-localloop.xml:/root/deploy/example-idscp2-localloop.xml ports: - "5005:5005" - "9292:9292" @@ -42,6 +22,7 @@ services: example-internal: aliases: - consumer-core + - provider-core networks: example-internal: diff --git a/examples/example-getting-started/example-idscp-localloop.xml b/examples/example-getting-started/example-idscp2-localloop.xml similarity index 86% rename from examples/example-getting-started/example-idscp-localloop.xml rename to examples/example-getting-started/example-idscp2-localloop.xml index 047dde31d..d7a35dc99 100644 --- a/examples/example-getting-started/example-idscp-localloop.xml +++ b/examples/example-getting-started/example-idscp2-localloop.xml @@ -28,17 +28,17 @@ - + Message at $simple{date:now:yyyy-MM-dd HH:mm:ss} - + - - + + diff --git a/examples/example-getting-started/system.properties b/examples/example-getting-started/system.properties deleted file mode 100644 index bc0db3a40..000000000 --- a/examples/example-getting-started/system.properties +++ /dev/null @@ -1,154 +0,0 @@ -################################################################################ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -################################################################################ - -# -# The properties defined in this file will be made available through system -# properties at the very beginning of the Karaf's boot process. -# - - -# Log level when the pax-logging service is not available -# This level will only be used while the pax-logging service bundle -# is not fully available. -# To change log levels, please refer to the org.ops4j.pax.logging.cfg file -# instead. -org.ops4j.pax.logging.DefaultServiceLog.level = ERROR - -# -# Name of this Karaf instance. -# -karaf.name = root - -# -# Default repository where bundles will be loaded from before using -# other Maven repositories. For the full Maven configuration, see -# the org.ops4j.pax.url.mvn.cfg file. -# -karaf.default.repository = system - -# -# Location of a shell script that will be run when starting a shell -# session. This script can be used to create aliases and define -# additional commands. -# -karaf.shell.init.script = shell.init.script - -# -# Sets the maximum size of the shell command history. If not set, -# defaults to 500 entries. Setting to 0 will disable history. -# -# karaf.shell.history.maxSize = 0 - -# -# Deletes the entire karaf.data directory at every start -# -karaf.clean.all = false - -# -# Deletes the karaf.data/cache directory at every start -# -karaf.clean.cache = true - -# -# User name for the Karaf local console -# -karaf.local.user = karaf - -# -# Roles to use when for the default user in the local Karaf console. -# -# The syntax is the following: -# [classname:]principal -# where classname is the class name of the principal object -# (defaults to org.apache.karaf.jaas.modules.RolePrincipal) -# and principal is the name of the principal of that class -# (defaults to instance). -# -karaf.local.roles = admin,manager,viewer,systembundles - -# -# Set this empty property to avoid errors when validating xml documents. -# -xml.catalog.files = - -# -# Suppress the bell in the console when hitting backspace too many times -# for example -# -jline.nobell = true - -# -# ServiceMix specs options -# -org.apache.servicemix.specs.debug = false -org.apache.servicemix.specs.timeout = 0 - -# -# Settings for the OSGi 4.3 Weaving -# By default, we will not weave any classes. Change this setting to include classes -# that you application needs to have woven. -# -org.apache.aries.proxy.weaving.enabled = none -# Classes not to weave - Aries default + Xerces which is known to have issues. -org.apache.aries.proxy.weaving.disabled = org.objectweb.asm.*,org.slf4j.*,org.apache.log4j.*,javax.*,org.apache.xerces.* - -# -# By default, only Karaf shell commands are secured, but additional services can be -# secured by expanding this filter -# -karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*)) - -# -# By default, if there's no ACL policy for a certain karaf command, this command is allowed to access -# without the RBAC. We can change this behavior by enable the following property, which means -# if a karaf command has no corresponding ACL then access it must have one of the karaf.secured.command.compulsory.roles -# -#karaf.secured.command.compulsory.roles=admin - -# -# Security properties -# -# To enable OSGi security, uncomment the properties below, -# install the framework-security feature and restart. -# -#java.security.policy=${karaf.etc}/all.policy -#org.osgi.framework.security=osgi -#org.osgi.framework.trust.repositories=${karaf.etc}/trustStore.ks - -# -# HA/Lock configuration -# -# Karaf uses a lock mechanism to know which instance is the master (HA) -# The lock can be on the filesystem (default) or on a database. -# -# See http://karaf.apache.org/manual/latest/users-guide/failover.html for details. -# -# Even using a single instance, Karaf creates the lock file -# You can specify the location of the lock file using the -# karaf.lock.dir=/path/to/the/directory/containing/the/lock -# -# By default, the slave instances start but are passive. -# If you want to prevent the slave instances startup, you can use -# the karaf.lock.slave.block property (false by default): -# karaf.lock.slave.block=true - -javax.net.ssl.keyStore=${karaf.etc}/client-keystore.jks -javax.net.ssl.keyStorePassword=password -javax.net.ssl.trustStore=${karaf.etc}/client-truststore.jks -javax.net.ssl.trustStorePassword=password \ No newline at end of file diff --git a/examples/example-idscp-localhost/README.md b/examples/example-idscp-localhost/README.md deleted file mode 100644 index b857a31cb..000000000 --- a/examples/example-idscp-localhost/README.md +++ /dev/null @@ -1,19 +0,0 @@ -This is an docker-compose override file for example-idscp featuring communication over localhost (or any other test network). - -It relies on the docker0 bridge using the gateway IP 172.17.0.1 (default value for docker setups). - -*NOTE: Publish the IDSCP port (TCP 9292, see docker-compose-consumer.yaml), otherwise consumer-core will not listen on localhost!* - -Usage (assumes example-idscp as working directory): -`docker-compose -f docker-compose-provider.yaml -f ../example-idscp-localhost/docker-compose-provider.override.yaml up` - -The following lines are overridden in the provider YAML file (consumer remains unchanged): -``` -provider-core: - extra_hosts: - - "consumer-core:172.17.0.1" -``` -Due to this directive, the provider will connect to localhost over bridge0, -instead of contacting the consumer directly via the `ids-wide` network. - -The IP address can be adjusted to another address of a machine where an example consumer is running. \ No newline at end of file diff --git a/examples/example-idscp-localhost/docker-compose-provider.override.yaml b/examples/example-idscp-localhost/docker-compose-provider.override.yaml deleted file mode 100644 index a0e964afd..000000000 --- a/examples/example-idscp-localhost/docker-compose-provider.override.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# NOTE: Publish the IDSCP port (TCP 9292, see docker-compose-consumer.yaml), otherwise consumer-core will not listen on localhost! - -# Use from directory "example-idscp" like this: -# docker-compose -f docker-compose-provider.yaml -f ../example-idscp-localhost/docker-compose-provider.override.yaml up - -version: '3' -services: - - provider-core: - extra_hosts: - - "consumer-core:172.17.0.1" \ No newline at end of file diff --git a/examples/example-idscp/README.md b/examples/example-idscp/README.md deleted file mode 100644 index ce4704476..000000000 --- a/examples/example-idscp/README.md +++ /dev/null @@ -1,6 +0,0 @@ -This example demonstrates the conversion of MQTT messages (using Eclipse Paho) -and publishing via a web interface using the Trusted Connector. - -Documentation is located at https://industrial-data-space.github.io/trusted-connector-documentation/docs/rest/ - -(c) Fraunhofer AISEC 2018 \ No newline at end of file diff --git a/examples/example-idscp/docker-compose-consumer.yaml b/examples/example-idscp/docker-compose-consumer.yaml deleted file mode 100644 index 23eb965af..000000000 --- a/examples/example-idscp/docker-compose-consumer.yaml +++ /dev/null @@ -1,51 +0,0 @@ -version: '3' -services: - - # TPM simulator - ids-tpmsim-consumer: - image: fraunhoferaisec/tpmsim:${EXAMPLE_TAG:-develop} - volumes: - # Always extract a "clean state" for our TPM simulator to prevent DA lockout issues - - ../tpmsim/tpmsim_data.tar:/tpmsim_data.tar - networks: - - consumer-internal - - # The core platform, mounts docker control socket and route definition into the image - consumer-core: - image: fraunhoferaisec/trusted-connector-core:${EXAMPLE_TAG:-develop} - tty: true - stdin_open: true - volumes: - - ../log/:/root/log/ - - /var/run/docker.sock:/var/run/docker.sock - - ./system.properties:/root/etc/system.properties - - ../tpmsim/rootCA.crt:/root/etc/rootca-cert.pem - - ../cert-stores/consumer-keystore.p12:/root/etc/consumer-keystore.p12 - - ../cert-stores/truststore.p12:/root/etc/truststore.p12 - - ./example-consumer-routes.xml:/root/deploy/example-consumer-routes.xml - environment: - - TPM_HOST=ids-tpmsim-consumer - # Enable this port mappings for debugging or UI access from localhost -# ports: -# - "5005:5005" -# - "8181:8181" -# - "8443:8443" - # Enable this port mapping (along with "ports:" above) to allow access to IDSCP from outside the ids-wide network -# - "9292:9292" - networks: - - ids-wide - - consumer-internal - - # Data App (REST consumer, displays web page) - consumer-app: - image: fraunhoferaisec/example-server:${EXAMPLE_TAG:-develop} - ports: - - "8081:8081" - networks: - - consumer-internal - -networks: - ids-wide: - driver: bridge - consumer-internal: - driver: bridge diff --git a/examples/example-idscp/docker-compose-provider.yaml b/examples/example-idscp/docker-compose-provider.yaml deleted file mode 100644 index 298f2513d..000000000 --- a/examples/example-idscp/docker-compose-provider.yaml +++ /dev/null @@ -1,53 +0,0 @@ -version: '3' -services: - - # TPM simulator - ids-tpmsim-provider: - image: fraunhoferaisec/tpmsim:${EXAMPLE_TAG:-develop} - volumes: - # Always extract a "clean state" for our TPM simulator to prevent DA lockout issues - - ../tpmsim/tpmsim_data.tar:/tpmsim_data.tar - networks: - - provider-internal - - # The core platform, mounts docker control socket and route definition into the image - provider-core: - image: fraunhoferaisec/trusted-connector-core:${EXAMPLE_TAG:-develop} - tty: true - stdin_open: true - volumes: - - ../log/:/root/log/ - - /var/run/docker.sock:/var/run/docker.sock - - ./system.properties:/root/etc/system.properties - - ../tpmsim/rootCA.crt:/root/etc/rootca-cert.pem - - ../cert-stores/provider-keystore.p12:/root/etc/provider-keystore.p12 - - ../cert-stores/truststore.p12:/root/etc/truststore.p12 - - ./example-provider-routes.xml:/root/deploy/example-provider-routes.xml - environment: - - TPM_HOST=ids-tpmsim-provider - # Enable this lines for debugging or UI access from localhost -# ports: -# - "5005:5005" -# - "8181:8181" -# - "8443:8443" - networks: - - ids-wide - - provider-internal - - # Mosquitto MQTT broker - mqtt-broker: - image: eclipse-mosquitto:latest - networks: - - provider-internal - - # Sensor data provider - provider-app: - image: fraunhoferaisec/example-client:${EXAMPLE_TAG:-develop} - networks: - - provider-internal - -networks: - ids-wide: - driver: bridge - provider-internal: - driver: bridge diff --git a/examples/example-idscp/docker-compose-ttp.yaml b/examples/example-idscp/docker-compose-ttp.yaml deleted file mode 100644 index 0ff6c73df..000000000 --- a/examples/example-idscp/docker-compose-ttp.yaml +++ /dev/null @@ -1,17 +0,0 @@ -version: '3' -services: - - # TPM trusted third party (RAT repository) - ids-ttpsim: - image: fraunhoferaisec/ttpsim:${EXAMPLE_TAG:-develop} - # Enable this port mapping to access TTP from outside the ids-wide network -# ports: -# - "31337:31337" - networks: - ids-wide: - aliases: - - repository.aisec.fraunhofer.de - -networks: - ids-wide: - driver: bridge diff --git a/examples/example-idscp/example-client/Dockerfile b/examples/example-idscp/example-client/Dockerfile deleted file mode 100644 index 9cd1c2869..000000000 --- a/examples/example-idscp/example-client/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM node:alpine - -WORKDIR /app - -ADD package.json /app -RUN npm install - -ADD app.js /app - -EXPOSE 8080 - -ENTRYPOINT [ "node", "app.js" ] diff --git a/examples/example-idscp/example-client/app.js b/examples/example-idscp/example-client/app.js deleted file mode 100644 index ae4552b3d..000000000 --- a/examples/example-idscp/example-client/app.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - Example of a very simple MQTT consumer app. - - This app subscribes to events at a public MQTT broker and makes them - available by a REST API. For demonstration purposes, it continuously - publishes random values under the subscribed MQTT topic. - - (C) Fraunhofer AISEC, 2017 -*/ - -// Start MQTT client -const mqtt = require('mqtt'); -const client = mqtt.connect('mqtt://mqtt-broker'); -const TEMP_TOPIC = 'ids-example-010/temp'; - -// React on MQTT connection -client.on('connect', () => { - console.log("Connected to MQTT broker") - client.subscribe(TEMP_TOPIC) -}) - -// React on received MQTT messages -client.on('message', (topic, message) => { - switch (topic) { - case TEMP_TOPIC: - console.log('Published and Received temp %s', message); - break; - default: - console.log('No handler for topic %s', topic); - } -}) - -// simulate sensor data by publishing random temperature data to MQTT broker -setInterval(() => { - client.publish(TEMP_TOPIC, String(Math.random() * (35 - 10) + 10)); -}, 1000) \ No newline at end of file diff --git a/examples/example-idscp/example-client/package.json b/examples/example-idscp/example-client/package.json deleted file mode 100644 index 41e8030ed..000000000 --- a/examples/example-idscp/example-client/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "@FraunhoferAISEC/ids-example-010-client", - "version": "1.0.0", - "description": "A sample application retrieving MQTT data and providing it as REST service", - "main": "controller.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "style": "standard" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/industrial-data-space/trusted-connector.git" - }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/FraunhoferAISEC" - }, - "homepage": "https://github.com/FraunhoferAISEC", - "dependencies": { - "mqtt": "^2.18.8" - }, - "devDependencies": { - "standard": "^12.0.1" - } -} diff --git a/examples/example-idscp/example-consumer-routes.xml b/examples/example-idscp/example-consumer-routes.xml deleted file mode 100644 index 99812e3d5..000000000 --- a/examples/example-idscp/example-consumer-routes.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/example-idscp/example-provider-routes.xml b/examples/example-idscp/example-provider-routes.xml deleted file mode 100644 index 013a25312..000000000 --- a/examples/example-idscp/example-provider-routes.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/example-idscp/example-server/Dockerfile b/examples/example-idscp/example-server/Dockerfile deleted file mode 100644 index 234c2858b..000000000 --- a/examples/example-idscp/example-server/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM node:alpine - -WORKDIR /app - -ADD package.json /app -RUN npm install - -ADD app.js /app - -EXPOSE 8081 - -ENTRYPOINT [ "node", "app.js" ] \ No newline at end of file diff --git a/examples/example-idscp/example-server/app.js b/examples/example-idscp/example-server/app.js deleted file mode 100644 index e4c55bec7..000000000 --- a/examples/example-idscp/example-server/app.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - Example of a very simple REST consumer app. - - This app accepts sensor values from POST requests to - http://:8081/temp - and displays them under - http://:8081/ - - For demonstration purposes only. - - (C) Fraunhofer AISEC, 2017 -*/ -var temp = 0 - -// Start REST server -var express = require('express') - , app = express() - -// just use raw body data -var bodyParser = require('body-parser') -var options = { - inflate: true, - limit: '10kb', - type: 'text/xml' -}; -app.use( bodyParser.raw(options) ); - -// Start REST endpoint /temp -app.post('/temp', function (req, res) { - temp = req.body - console.log('received temp ' + temp) - res.end('OK') -}) - -// Start web page / -app.get('/', function (req, res, next) { - try { - var html = '

Temp '+Number(temp).toFixed(2)+'

' - res.send(html) - } catch (e) { - next(e) - } -}) - -var server = app.listen(8081, function () { - var host = server.address().address - var port = server.address().port - console.log("REST API listening at http://%s:%s", host, port) -}) diff --git a/examples/example-idscp/example-server/package.json b/examples/example-idscp/example-server/package.json deleted file mode 100644 index 8759276f8..000000000 --- a/examples/example-idscp/example-server/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "@FraunhoferAISEC/ids-example-010-client", - "version": "1.0.0", - "description": "A sample application retrieving MQTT data and providing it as REST service", - "main": "controller.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "style": "standard" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/industrial-data-space/trusted-connector.git" - }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/FraunhoferAISEC" - }, - "homepage": "https://github.com/FraunhoferAISEC", - "dependencies": { - "body-parser": "^1.18.3", - "express": "^4.16.4" - }, - "devDependencies": { - "standard": "^12.0.1" - } -} diff --git a/examples/example-idscp/system.properties b/examples/example-idscp/system.properties deleted file mode 100644 index bc0db3a40..000000000 --- a/examples/example-idscp/system.properties +++ /dev/null @@ -1,154 +0,0 @@ -################################################################################ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -################################################################################ - -# -# The properties defined in this file will be made available through system -# properties at the very beginning of the Karaf's boot process. -# - - -# Log level when the pax-logging service is not available -# This level will only be used while the pax-logging service bundle -# is not fully available. -# To change log levels, please refer to the org.ops4j.pax.logging.cfg file -# instead. -org.ops4j.pax.logging.DefaultServiceLog.level = ERROR - -# -# Name of this Karaf instance. -# -karaf.name = root - -# -# Default repository where bundles will be loaded from before using -# other Maven repositories. For the full Maven configuration, see -# the org.ops4j.pax.url.mvn.cfg file. -# -karaf.default.repository = system - -# -# Location of a shell script that will be run when starting a shell -# session. This script can be used to create aliases and define -# additional commands. -# -karaf.shell.init.script = shell.init.script - -# -# Sets the maximum size of the shell command history. If not set, -# defaults to 500 entries. Setting to 0 will disable history. -# -# karaf.shell.history.maxSize = 0 - -# -# Deletes the entire karaf.data directory at every start -# -karaf.clean.all = false - -# -# Deletes the karaf.data/cache directory at every start -# -karaf.clean.cache = true - -# -# User name for the Karaf local console -# -karaf.local.user = karaf - -# -# Roles to use when for the default user in the local Karaf console. -# -# The syntax is the following: -# [classname:]principal -# where classname is the class name of the principal object -# (defaults to org.apache.karaf.jaas.modules.RolePrincipal) -# and principal is the name of the principal of that class -# (defaults to instance). -# -karaf.local.roles = admin,manager,viewer,systembundles - -# -# Set this empty property to avoid errors when validating xml documents. -# -xml.catalog.files = - -# -# Suppress the bell in the console when hitting backspace too many times -# for example -# -jline.nobell = true - -# -# ServiceMix specs options -# -org.apache.servicemix.specs.debug = false -org.apache.servicemix.specs.timeout = 0 - -# -# Settings for the OSGi 4.3 Weaving -# By default, we will not weave any classes. Change this setting to include classes -# that you application needs to have woven. -# -org.apache.aries.proxy.weaving.enabled = none -# Classes not to weave - Aries default + Xerces which is known to have issues. -org.apache.aries.proxy.weaving.disabled = org.objectweb.asm.*,org.slf4j.*,org.apache.log4j.*,javax.*,org.apache.xerces.* - -# -# By default, only Karaf shell commands are secured, but additional services can be -# secured by expanding this filter -# -karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*)) - -# -# By default, if there's no ACL policy for a certain karaf command, this command is allowed to access -# without the RBAC. We can change this behavior by enable the following property, which means -# if a karaf command has no corresponding ACL then access it must have one of the karaf.secured.command.compulsory.roles -# -#karaf.secured.command.compulsory.roles=admin - -# -# Security properties -# -# To enable OSGi security, uncomment the properties below, -# install the framework-security feature and restart. -# -#java.security.policy=${karaf.etc}/all.policy -#org.osgi.framework.security=osgi -#org.osgi.framework.trust.repositories=${karaf.etc}/trustStore.ks - -# -# HA/Lock configuration -# -# Karaf uses a lock mechanism to know which instance is the master (HA) -# The lock can be on the filesystem (default) or on a database. -# -# See http://karaf.apache.org/manual/latest/users-guide/failover.html for details. -# -# Even using a single instance, Karaf creates the lock file -# You can specify the location of the lock file using the -# karaf.lock.dir=/path/to/the/directory/containing/the/lock -# -# By default, the slave instances start but are passive. -# If you want to prevent the slave instances startup, you can use -# the karaf.lock.slave.block property (false by default): -# karaf.lock.slave.block=true - -javax.net.ssl.keyStore=${karaf.etc}/client-keystore.jks -javax.net.ssl.keyStorePassword=password -javax.net.ssl.trustStore=${karaf.etc}/client-truststore.jks -javax.net.ssl.trustStorePassword=password \ No newline at end of file diff --git a/examples/example-idscp/.env b/examples/example-idscp2-uc/.env similarity index 100% rename from examples/example-idscp/.env rename to examples/example-idscp2-uc/.env diff --git a/examples/example-idscp2-uc/README.md b/examples/example-idscp2-uc/README.md new file mode 100644 index 000000000..39acbe03f --- /dev/null +++ b/examples/example-idscp2-uc/README.md @@ -0,0 +1,11 @@ +# IDSCP2 communication examples + +This example demonstrates client-server communication between trusted connectors via the IDSCP2 protocol, +including LUCON UC (Usage Control), limiting execution to a particular docker container, identified by its content hash. + +The example is started in the same way as described in `example-idscp2/README.md`, with the only difference that +container names in `exec` commands (`server-core` and `client-core`) switch places. + +If the UC demo fails, check whether the repo digest needs to be adapted in the XML file`example-idscp2-server.xml` +(last part of DockerHub URI). +You can show the most recent digest using the command `docker images --digests jmalloc/echo-server`. \ No newline at end of file diff --git a/examples/example-idscp2-uc/docker-compose-client.yaml b/examples/example-idscp2-uc/docker-compose-client.yaml new file mode 100644 index 000000000..55f60e83f --- /dev/null +++ b/examples/example-idscp2-uc/docker-compose-client.yaml @@ -0,0 +1,33 @@ +version: '3' +services: + + # The core platform, mounts docker control socket and route definition into the image + consumer-core: + image: fraunhoferaisec/trusted-connector-core:${EXAMPLE_TAG:-develop} + tty: true + stdin_open: true + volumes: + - ../log/:/root/log/ + - /var/run/docker.sock:/var/run/docker.sock + - ../cert-stores/provider-keystore.p12:/root/etc/provider-keystore.p12 + - ../cert-stores/truststore.p12:/root/etc/truststore.p12 + - ./example-idscp2-client.xml:/root/deploy/example-idscp2-client.xml + # Enable this port mappings for debugging or UI access from localhost +# ports: +# - "5005:5005" +# - "8181:8181" +# - "8443:8443" + networks: + - ids-wide + - provider-internal + + echo-server: + image: jmalloc/echo-server@sha256:c461e7e54d947a8777413aaf9c624b4ad1f1bac5d8272475da859ae82c1abd7d + networks: + - provider-internal + +networks: + ids-wide: + driver: bridge + provider-internal: + driver: bridge diff --git a/examples/example-idscp2-uc/docker-compose-server.yaml b/examples/example-idscp2-uc/docker-compose-server.yaml new file mode 100644 index 000000000..024c3546f --- /dev/null +++ b/examples/example-idscp2-uc/docker-compose-server.yaml @@ -0,0 +1,25 @@ +version: '3' +services: + + # The core platform, mounts docker control socket and route definition into the image + provider-core: + image: fraunhoferaisec/trusted-connector-core:${EXAMPLE_TAG:-develop} + tty: true + stdin_open: true + volumes: + - ../log/:/root/log/ + - /var/run/docker.sock:/var/run/docker.sock + - ../cert-stores/consumer-keystore.p12:/root/etc/consumer-keystore.p12 + - ../cert-stores/truststore.p12:/root/etc/truststore.p12 + - ./example-idscp2-server.xml:/root/deploy/example-idscp2-server.xml + # Enable this port mappings for debugging or UI access from localhost +# ports: +# - "5005:5005" +# - "8181:8181" +# - "8443:8443" + networks: + - ids-wide + +networks: + ids-wide: + driver: bridge diff --git a/examples/example-idscp2-uc/example-idscp2-client.xml b/examples/example-idscp2-uc/example-idscp2-client.xml new file mode 100644 index 000000000..c75908056 --- /dev/null +++ b/examples/example-idscp2-uc/example-idscp2-client.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + https://example.com/some_artifact + + + + + + + ${exchangeProperty.ids-type} == 'ContractResponseMessage' + + + + + + + + ${null} + + + + + + + + https://example.com/some_artifact + + + + + + + ${exchangeProperty.ids-type} == 'ArtifactResponseMessage' + + + + + + + + + + + + + diff --git a/examples/example-idscp2-uc/example-idscp2-server.xml b/examples/example-idscp2-uc/example-idscp2-server.xml new file mode 100644 index 000000000..94db29984 --- /dev/null +++ b/examples/example-idscp2-uc/example-idscp2-server.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ${exchangeProperty.ids-type} == 'ContractRequestMessage' + + + https://hub.docker.com/layers/jmalloc/echo-server/latest/images/sha256-c461e7e54d947a8777413aaf9c624b4ad1f1bac5d8272475da859ae82c1abd7d#8080 + + + + + ${exchangeProperty.ids-type} == 'ContractAgreementMessage' + + + + + ${null} + + + ${exchangeProperty.ids-type} == 'ArtifactRequestMessage' + + + + + + + ${null} + + + + + + + diff --git a/examples/example-idscp2/.env b/examples/example-idscp2/.env new file mode 100644 index 000000000..a424a7d41 --- /dev/null +++ b/examples/example-idscp2/.env @@ -0,0 +1,2 @@ +# This defines the tag used for docker-compose example YAML files in the current directory +EXAMPLE_TAG=develop \ No newline at end of file diff --git a/examples/example-idscp2/README.md b/examples/example-idscp2/README.md new file mode 100644 index 000000000..cd695c1fa --- /dev/null +++ b/examples/example-idscp2/README.md @@ -0,0 +1,22 @@ +# IDSCP2 communication examples + +This examples demonstrate data transfer between trusted connectors via the IDSCP2 protocol. + +### Default client-server-example + +First, start the server (consumer) with the command `docker-compose -f docker-compose-server.yaml up`. +When the Karaf shell appears, you may attach to it via a separate SSH client connection using the command +`docker-compose -f docker-compose-server.yaml exec server-core bin/client`, and show logs output `log:tail`. + +Second, start the client (provider) using the command `docker-compose -f docker-compose-provider.yaml up`. +When the Karaf shell appears, you may use `docker-compose -f docker-compose-provider.yaml exec client-core bin/client` +and `log:tail` analogous to the server. + +### Broadcast example + +For testing one-to-many broadcasting, the server and client can be started analogous to the client-server-example, +with the following command modifications: + +- Write `docker-compose-broadcast-server.yaml` and `docker-compose-broadcast-client.yaml` + instead of `docker-compose-server.yaml` and `docker-compose-client.yaml`, respectively. +- Container names for `exec` commands (`server-core` and `client-core`) switch places. \ No newline at end of file diff --git a/examples/example-idscp2/docker-compose-broadcast-client.yaml b/examples/example-idscp2/docker-compose-broadcast-client.yaml new file mode 100644 index 000000000..8a0ed97aa --- /dev/null +++ b/examples/example-idscp2/docker-compose-broadcast-client.yaml @@ -0,0 +1,25 @@ +version: '3' +services: + + # The core platform, mounts docker control socket and route definition into the image + consumer-core: + image: fraunhoferaisec/trusted-connector-core:${EXAMPLE_TAG:-develop} + tty: true + stdin_open: true + volumes: + - ../log/:/root/log/ + - /var/run/docker.sock:/var/run/docker.sock + - ../cert-stores/consumer-keystore.p12:/root/etc/consumer-keystore.p12 + - ../cert-stores/truststore.p12:/root/etc/truststore.p12 + - ./example-idscp2-client-broadcast.xml:/root/deploy/example-idscp2-client.xml + # Enable this port mappings for debugging or UI access from localhost +# ports: +# - "5005:5005" +# - "8181:8181" +# - "8443:8443" + networks: + - ids-wide + +networks: + ids-wide: + driver: bridge diff --git a/examples/example-idscp2/docker-compose-broadcast-server.yaml b/examples/example-idscp2/docker-compose-broadcast-server.yaml new file mode 100644 index 000000000..77a29a9fb --- /dev/null +++ b/examples/example-idscp2/docker-compose-broadcast-server.yaml @@ -0,0 +1,25 @@ +version: '3' +services: + + # The core platform, mounts docker control socket and route definition into the image + provider-core: + image: fraunhoferaisec/trusted-connector-core:${EXAMPLE_TAG:-develop} + tty: true + stdin_open: true + volumes: + - ../log/:/root/log/ + - /var/run/docker.sock:/var/run/docker.sock + - ../cert-stores/provider-keystore.p12:/root/etc/provider-keystore.p12 + - ../cert-stores/truststore.p12:/root/etc/truststore.p12 + - ./example-idscp2-server-broadcast.xml:/root/deploy/example-idscp2-server.xml + # Enable this port mappings for debugging or UI access from localhost +# ports: +# - "5005:5005" +# - "8181:8181" +# - "8443:8443" + networks: + - ids-wide + +networks: + ids-wide: + driver: bridge diff --git a/examples/example-idscp2/docker-compose-client.yaml b/examples/example-idscp2/docker-compose-client.yaml new file mode 100644 index 000000000..fe1124ffd --- /dev/null +++ b/examples/example-idscp2/docker-compose-client.yaml @@ -0,0 +1,25 @@ +version: '3' +services: + + # The core platform, mounts docker control socket and route definition into the image + provider-core: + image: fraunhoferaisec/trusted-connector-core:${EXAMPLE_TAG:-develop} + tty: true + stdin_open: true + volumes: + - ../log/:/root/log/ + - /var/run/docker.sock:/var/run/docker.sock + - ../cert-stores/provider-keystore.p12:/root/etc/provider-keystore.p12 + - ../cert-stores/truststore.p12:/root/etc/truststore.p12 + - ./example-idscp2-client.xml:/root/deploy/example-idscp2-client.xml + # Enable this port mappings for debugging or UI access from localhost +# ports: +# - "5005:5005" +# - "8181:8181" +# - "8443:8443" + networks: + - ids-wide + +networks: + ids-wide: + driver: bridge diff --git a/examples/example-idscp2/docker-compose-server.yaml b/examples/example-idscp2/docker-compose-server.yaml new file mode 100644 index 000000000..8d5ea6152 --- /dev/null +++ b/examples/example-idscp2/docker-compose-server.yaml @@ -0,0 +1,25 @@ +version: '3' +services: + + # The core platform, mounts docker control socket and route definition into the image + consumer-core: + image: fraunhoferaisec/trusted-connector-core:${EXAMPLE_TAG:-develop} + tty: true + stdin_open: true + volumes: + - ../log/:/root/log/ + - /var/run/docker.sock:/var/run/docker.sock + - ../cert-stores/consumer-keystore.p12:/root/etc/consumer-keystore.p12 + - ../cert-stores/truststore.p12:/root/etc/truststore.p12 + - ./example-idscp2-server.xml:/root/deploy/example-idscp2-server.xml + # Enable this port mappings for debugging or UI access from localhost +# ports: +# - "5005:5005" +# - "8181:8181" +# - "8443:8443" + networks: + - ids-wide + +networks: + ids-wide: + driver: bridge diff --git a/examples/example-idscp2/example-idscp2-client-broadcast.xml b/examples/example-idscp2/example-idscp2-client-broadcast.xml new file mode 100644 index 000000000..b080f3821 --- /dev/null +++ b/examples/example-idscp2/example-idscp2-client-broadcast.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + ${null} + + + + + + diff --git a/examples/example-idscp2/example-idscp2-client.xml b/examples/example-idscp2/example-idscp2-client.xml new file mode 100644 index 000000000..e005090a5 --- /dev/null +++ b/examples/example-idscp2/example-idscp2-client.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + PING + + + ping + + + + + + + + ${null} + + + + + + diff --git a/examples/example-idscp2/example-idscp2-server-broadcast.xml b/examples/example-idscp2/example-idscp2-server-broadcast.xml new file mode 100644 index 000000000..097ddf003 --- /dev/null +++ b/examples/example-idscp2/example-idscp2-server-broadcast.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + BROADCAST + + + broadcast + + + + + + + + diff --git a/examples/example-idscp2/example-idscp2-server.xml b/examples/example-idscp2/example-idscp2-server.xml new file mode 100644 index 000000000..9114d41d2 --- /dev/null +++ b/examples/example-idscp2/example-idscp2-server.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + PONG + + + pong + + + + + + + diff --git a/examples/route-examples/demo-route.md b/examples/route-examples/demo-route.md new file mode 100644 index 000000000..99322c5fe --- /dev/null +++ b/examples/route-examples/demo-route.md @@ -0,0 +1,7 @@ +The UC demo requires a running connector that matches the UC config given in the XML route. The `jmalloc/echo-server` may be exchanged with something more appropriate if desired. + +The following steps are required: + +- First, start UC demo container via `docker run -d -p 8080:8080 --name test jmalloc/echo-server`. +- The IP address in ``-statement must be adapted for the new container. Display current IP address via `docker inspect --format='{{.NetworkSettings.IPAddress}}' test`. +- If the UC demo fails, check whether the repo digest needs to be adapted in XML (last part of DockerHub URI). Show recent digest with `docker inspect --format='{{.RepoDigests}}' jmalloc/echo-server` \ No newline at end of file diff --git a/examples/route-examples/demo-route.xml b/examples/route-examples/demo-route.xml new file mode 100644 index 000000000..bedb85a63 --- /dev/null +++ b/examples/route-examples/demo-route.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${exchangeProperty.ids-type} == 'ContractRequestMessage' + + + https://hub.docker.com/layers/jmalloc/echo-server/latest/images/sha256-c461e7e54d947a8777413aaf9c624b4ad1f1bac5d8272475da859ae82c1abd7d#8080 + + + + + + ${exchangeProperty.ids-type} == 'ContractAgreementMessage' + + + + + ${null} + + + + ${exchangeProperty.ids-type} == 'ArtifactRequestMessage' + + + + + + + + ${null} + + + + + + + + + true + ${null} + + + https://example.com/some_artifact + + + + + 5000 + + + + + false + ${null} + + + https://example.com/unavailable_artifact + + + + + 5000 + + + + + true + ${null} + + + https://example.com/some_artifact + + + + + 5000 + + + + + false + ${null} + + + https://example.com/unavailable_artifact + + + + + 5000 + + + + + + + + + + + + + + ${exchangeProperty.ids-type} == 'ContractResponseMessage' + + + + + + ${exchangeProperty.ids-type} == 'ArtifactResponseMessage' + + + + + + ${null} + + + + + + ${null} + + + + + diff --git a/examples/route-examples/example-idscp-localloop.xml b/examples/route-examples/example-idscp-localloop.xml deleted file mode 100644 index eb6d8fab5..000000000 --- a/examples/route-examples/example-idscp-localloop.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Message at $simple{date:now:yyyy-MM-dd HH:mm:ss} - - - - - - - - - - - - - diff --git a/examples/route-examples/example-idscp2-client-broadcast.xml b/examples/route-examples/example-idscp2-client-broadcast.xml new file mode 100644 index 000000000..20263637c --- /dev/null +++ b/examples/route-examples/example-idscp2-client-broadcast.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/route-examples/example-idscp2-client.xml b/examples/route-examples/example-idscp2-client.xml new file mode 100644 index 000000000..637511eda --- /dev/null +++ b/examples/route-examples/example-idscp2-client.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + PING + + + ping + + + + + + + + + + + + + + + diff --git a/examples/route-examples/example-idscp2-server-broadcast.xml b/examples/route-examples/example-idscp2-server-broadcast.xml new file mode 100644 index 000000000..7a57ca681 --- /dev/null +++ b/examples/route-examples/example-idscp2-server-broadcast.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + BROADCAST + + + broadcast + + + + + + + + diff --git a/examples/route-examples/example-idscp2-server.xml b/examples/route-examples/example-idscp2-server.xml new file mode 100644 index 000000000..eca646e31 --- /dev/null +++ b/examples/route-examples/example-idscp2-server.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + PONG + + + pong + + + + + + + diff --git a/examples/templates/example-idscp/.env b/examples/templates/example-idscp2-uc/.env similarity index 100% rename from examples/templates/example-idscp/.env rename to examples/templates/example-idscp2-uc/.env diff --git a/examples/templates/example-idscp2/.env b/examples/templates/example-idscp2/.env new file mode 100644 index 000000000..0dc8eb9ee --- /dev/null +++ b/examples/templates/example-idscp2/.env @@ -0,0 +1,2 @@ +# This defines the tag used for docker-compose example YAML files in the current directory +EXAMPLE_TAG=${exampleTag} \ No newline at end of file diff --git a/examples/tpmsim/Dockerfile b/examples/tpmsim/Dockerfile index e484e35c5..177787e89 100644 --- a/examples/tpmsim/Dockerfile +++ b/examples/tpmsim/Dockerfile @@ -17,7 +17,7 @@ RUN apt-get update -qq && apt-get install -qq gawk libseccomp-dev \ # Removed selinux-policy-dev because of build error net-tools python3 python3-twisted trousers tpm-tools gnutls-bin gnutls-dev \ libtasn1-6 libtasn1-6-dev build-essential devscripts equivs socat -RUN git clone https://github.com/stefanberger/swtpm.git && cd swtpm && \ +RUN git clone https://github.com/stefanberger/swtpm.git && cd swtpm && git checkout stable-0.3.0 && \ ./autogen.sh && make -j4 && checkinstall --fstrans=no --pkgname=swtpm -y && cp swtpm*.deb ${BUILD_DIR} # tpm2d dependencies diff --git a/examples/trusted-connector-examples_4.0.0.zip b/examples/trusted-connector-examples_4.0.0.zip new file mode 100644 index 000000000..b88f64327 Binary files /dev/null and b/examples/trusted-connector-examples_4.0.0.zip differ diff --git a/examples/trusted-connector-examples_develop.zip b/examples/trusted-connector-examples_develop.zip index 2bbc2455e..4a1a8aaf4 100644 Binary files a/examples/trusted-connector-examples_develop.zip and b/examples/trusted-connector-examples_develop.zip differ diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738cbd..e708b1c02 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c1d54ccfd..be52383ef 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,5 @@ -#Tue Jun 25 19:31:12 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip -org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m \ No newline at end of file diff --git a/gradlew b/gradlew index af6708ff2..4f906e0c8 100755 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m"' +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -138,19 +156,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 0f8d5937c..ac1b06f93 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/ids-acme/build.gradle.kts b/ids-acme/build.gradle.kts index f562e2f74..cfc2a0b97 100644 --- a/ids-acme/build.gradle.kts +++ b/ids-acme/build.gradle.kts @@ -1,14 +1,9 @@ -import org.yaml.snakeyaml.Yaml - dependencies { @Suppress("UNCHECKED_CAST") val libraryVersions = - Yaml().load(File("${rootDir}/libraryVersions.yaml").inputStream()) as Map + rootProject.extra.get("libraryVersions") as Map providedByBundle(project(":ids-api")) { isTransitive = false } - providedByBundle("org.apache.logging.log4j", "log4j-core", libraryVersions["log4j"]) - providedByBundle("org.apache.logging.log4j", "log4j-slf4j-impl", libraryVersions["log4j"]) - providedByFeature("org.eclipse.jetty", "jetty-util", libraryVersions["jetty"]) providedByFeature("org.apache.karaf.scheduler", "org.apache.karaf.scheduler.core", libraryVersions["karaf"]) diff --git a/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/AcmeChallengeServer.kt b/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/AcmeChallengeServer.kt index b1251c6fe..d2323bce0 100644 --- a/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/AcmeChallengeServer.kt +++ b/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/AcmeChallengeServer.kt @@ -21,11 +21,11 @@ package de.fhg.aisec.ids.acme import de.fhg.aisec.ids.api.acme.AcmeClient import fi.iki.elonen.NanoHTTPD -import org.slf4j.LoggerFactory import java.io.ByteArrayInputStream import java.io.IOException import java.nio.charset.StandardCharsets import java.util.regex.Pattern +import org.slf4j.LoggerFactory object AcmeChallengeServer { const val TEXT_PLAIN = "text/plain" @@ -35,32 +35,40 @@ object AcmeChallengeServer { @Throws(IOException::class) fun startServer(acmeClient: AcmeClient, challengePort: Int) { - server = object : NanoHTTPD(challengePort) { - override fun serve(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { - val tokenMatcher = ACME_REGEX.matcher(session.uri) - if (!tokenMatcher.matches()) { - LOG.error("Received invalid ACME challenge {} ", session.uri) - return NanoHTTPD.newFixedLengthResponse( - NanoHTTPD.Response.Status.BAD_REQUEST, TEXT_PLAIN, null) - } - val token = tokenMatcher.group(1) - LOG.info("Received ACME challenge: {}", token) - val response = acmeClient.getChallengeAuthorization(token) - return if (response == null) { - LOG.warn("ACME challenge is unknown") - NanoHTTPD.newFixedLengthResponse( - NanoHTTPD.Response.Status.NOT_FOUND, TEXT_PLAIN, null) - } else { - LOG.info("ACME challenge response: {}", response) - val responseBytes = response.toByteArray(StandardCharsets.UTF_8) - NanoHTTPD.newFixedLengthResponse( + server = + object : NanoHTTPD(challengePort) { + override fun serve(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { + val tokenMatcher = ACME_REGEX.matcher(session.uri) + if (!tokenMatcher.matches()) { + LOG.error("Received invalid ACME challenge {} ", session.uri) + return NanoHTTPD.newFixedLengthResponse( + NanoHTTPD.Response.Status.BAD_REQUEST, + TEXT_PLAIN, + null + ) + } + val token = tokenMatcher.group(1) + LOG.info("Received ACME challenge: {}", token) + val response = acmeClient.getChallengeAuthorization(token) + return if (response == null) { + LOG.warn("ACME challenge is unknown") + NanoHTTPD.newFixedLengthResponse( + NanoHTTPD.Response.Status.NOT_FOUND, + TEXT_PLAIN, + null + ) + } else { + LOG.info("ACME challenge response: {}", response) + val responseBytes = response.toByteArray(StandardCharsets.UTF_8) + NanoHTTPD.newFixedLengthResponse( NanoHTTPD.Response.Status.OK, TEXT_PLAIN, ByteArrayInputStream(responseBytes), - responseBytes.size.toLong()) + responseBytes.size.toLong() + ) + } } } - } server?.let { it.start(NanoHTTPD.SOCKET_READ_TIMEOUT, true) LOG.debug("NanoHTTPD started") diff --git a/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/AcmeClientService.kt b/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/AcmeClientService.kt index 25166ab14..114bbdbf6 100644 --- a/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/AcmeClientService.kt +++ b/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/AcmeClientService.kt @@ -23,18 +23,6 @@ import de.fhg.aisec.ids.api.acme.AcmeClient import de.fhg.aisec.ids.api.acme.AcmeTermsOfService import de.fhg.aisec.ids.api.acme.SslContextFactoryReloadable import de.fhg.aisec.ids.api.settings.Settings -import org.apache.karaf.scheduler.Scheduler -import org.osgi.service.component.annotations.Activate -import org.osgi.service.component.annotations.Component -import org.osgi.service.component.annotations.Reference -import org.osgi.service.component.annotations.ReferenceCardinality -import org.shredzone.acme4j.* -import org.shredzone.acme4j.challenge.Http01Challenge -import org.shredzone.acme4j.exception.AcmeException -import org.shredzone.acme4j.exception.AcmeNetworkException -import org.shredzone.acme4j.util.CSRBuilder -import org.shredzone.acme4j.util.KeyPairUtils -import org.slf4j.LoggerFactory import java.io.IOException import java.io.InputStreamReader import java.net.URI @@ -49,29 +37,45 @@ import java.security.cert.X509Certificate import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.* +import org.apache.karaf.scheduler.Scheduler +import org.osgi.service.component.annotations.Activate +import org.osgi.service.component.annotations.Component +import org.osgi.service.component.annotations.Reference +import org.osgi.service.component.annotations.ReferenceCardinality +import org.shredzone.acme4j.* +import org.shredzone.acme4j.challenge.Http01Challenge +import org.shredzone.acme4j.exception.AcmeException +import org.shredzone.acme4j.exception.AcmeNetworkException +import org.shredzone.acme4j.util.CSRBuilder +import org.shredzone.acme4j.util.KeyPairUtils +import org.slf4j.LoggerFactory -@Component(immediate = true, name = "ids-acme-client", - // Every day at 3:00 (3 am) - property = [Scheduler.PROPERTY_SCHEDULER_EXPRESSION + "=0 0 3 * * ?"]) +@Component( + immediate = true, + name = "ids-acme-client", + // Every day at 3:00 (3 am) + property = [Scheduler.PROPERTY_SCHEDULER_EXPRESSION + "=0 0 3 * * ?"] +) class AcmeClientService : AcmeClient, Runnable { /* - * The following block subscribes this component to the Settings Service - */ - @Reference(cardinality = ReferenceCardinality.OPTIONAL) - private var settings: Settings? = null + * The following block subscribes this component to the Settings Service + */ + @Reference(cardinality = ReferenceCardinality.OPTIONAL) private var settings: Settings? = null private val sslReloadables = Collections.synchronizedSet(HashSet()) /* - * The following block subscribes this component to any SslContextFactoryReloader. - * - * A SslContextFactoryReloader is expected to refresh all TLS connections with new - * certificates from the key store. - */ - @Reference(name = "dynamic-tls-reload-service", - service = SslContextFactoryReloadable::class, - cardinality = ReferenceCardinality.MULTIPLE, - unbind = "unbindSslContextFactoryReloadable") + * The following block subscribes this component to any SslContextFactoryReloader. + * + * A SslContextFactoryReloader is expected to refresh all TLS connections with new + * certificates from the key store. + */ + @Reference( + name = "dynamic-tls-reload-service", + service = SslContextFactoryReloadable::class, + cardinality = ReferenceCardinality.MULTIPLE, + unbind = "unbindSslContextFactoryReloadable" + ) private fun bindSslContextFactoryReloadable(reloadable: SslContextFactoryReloadable) { LOG.info("Bound SslContextFactoryReloadable in AcmeClientService") this.sslReloadables.add(reloadable) @@ -94,13 +98,10 @@ class AcmeClientService : AcmeClient, Runnable { } catch (ioe: IOException) { return AcmeTermsOfService(tosUri!!.toString(), true, null) } - } catch (e: Exception) { LOG.error("ACME ToS retrieval error", e) - return AcmeTermsOfService(null, false, - e.javaClass.simpleName + ": " + e.message) + return AcmeTermsOfService(null, false, e.javaClass.simpleName + ": " + e.message) } - } override fun getChallengeAuthorization(challenge: String): String? { @@ -108,35 +109,32 @@ class AcmeClientService : AcmeClient, Runnable { } private fun ensureKeys(targetDirectory: Path) { - Arrays.asList("acme.key", "domain.key") - .forEach { keyFile -> - val keyFilePath = targetDirectory.resolve(keyFile) - if (!keyFilePath.toFile().exists()) { - val keyPair = KeyPairUtils.createKeyPair(4096) - try { - Files.newBufferedWriter(keyFilePath, StandardCharsets.UTF_8) - .use { fileWriter -> - KeyPairUtils.writeKeyPair(keyPair, fileWriter) - LOG.info( - "Successfully created RSA KeyPair: {}", - targetDirectory.resolve(keyFile) - .toAbsolutePath()) - } - } catch (e: IOException) { - LOG.error("Could not write key pair", e) - throw AcmeClientException(e) - } - + Arrays.asList("acme.key", "domain.key").forEach { keyFile -> + val keyFilePath = targetDirectory.resolve(keyFile) + if (!keyFilePath.toFile().exists()) { + val keyPair = KeyPairUtils.createKeyPair(4096) + try { + Files.newBufferedWriter(keyFilePath, StandardCharsets.UTF_8).use { fileWriter -> + KeyPairUtils.writeKeyPair(keyPair, fileWriter) + LOG.info( + "Successfully created RSA KeyPair: {}", + targetDirectory.resolve(keyFile).toAbsolutePath() + ) } + } catch (e: IOException) { + LOG.error("Could not write key pair", e) + throw AcmeClientException(e) } + } + } } private fun getACMEKeyPair(targetDirectory: Path): KeyPair { try { - Files.newBufferedReader( - targetDirectory.resolve("acme.key"), - StandardCharsets.UTF_8).use { - fileReader -> return KeyPairUtils.readKeyPair(fileReader) } + Files.newBufferedReader(targetDirectory.resolve("acme.key"), StandardCharsets.UTF_8) + .use { fileReader -> + return KeyPairUtils.readKeyPair(fileReader) + } } catch (e: IOException) { LOG.error("Could not read ACME key pair", e) throw AcmeClientException(e) @@ -144,7 +142,11 @@ class AcmeClientService : AcmeClient, Runnable { } override fun renewCertificate( - targetDirectory: Path, acmeServerUri: URI, domains: Array, challengePort: Int) { + targetDirectory: Path, + acmeServerUri: URI, + domains: Array, + challengePort: Int + ) { try { ensureKeys(targetDirectory) @@ -158,7 +160,8 @@ class AcmeClientService : AcmeClient, Runnable { while (true) { try { val session = Session(acmeServerUri) - account = AccountBuilder() + account = + AccountBuilder() .agreeToTermsOfService() .useKeyPair(getACMEKeyPair(targetDirectory)) .create(session) @@ -168,8 +171,10 @@ class AcmeClientService : AcmeClient, Runnable { break } catch (e: AcmeNetworkException) { // In case of ACME error, session creation has failed; return immediately. - LOG.warn("Could not connect to ACME server {}. Will not create certificate.", - acmeServerUri) + LOG.warn( + "Could not connect to ACME server {}. Will not create certificate.", + acmeServerUri + ) return } catch (e: AcmeException) { // In case of ACME error, session creation has failed; return immediately. @@ -181,8 +186,10 @@ class AcmeClientService : AcmeClient, Runnable { return } else { LOG.error( - "Got an IllegalArgumentException, maybe the ACME protocol handler " - + "is not available yet. Retry in 10 seconds...", iae) + "Got an IllegalArgumentException, maybe the ACME protocol handler " + + "is not available yet. Retry in 10 seconds...", + iae + ) // Wait 10 seconds before trying again try { Thread.sleep(10000) @@ -190,10 +197,8 @@ class AcmeClientService : AcmeClient, Runnable { LOG.error("Interrupt during 10-seconds-delay", ie) Thread.currentThread().interrupt() } - } } - } // Start ACME challenge responder @@ -203,91 +208,111 @@ class AcmeClientService : AcmeClient, Runnable { try { order = account.newOrder().domains(*domains).create() order - .authorizations - .parallelStream() - .map { authorization -> - authorization.findChallenge(Http01Challenge.TYPE)} - .forEach { challenge -> - challengeMap[challenge.token] = challenge.authorization - try { - // solve the challenge - challenge.trigger() - do { - try { - Thread.sleep(1000L) - } catch (ie: InterruptedException) { - LOG.error("Error while doing 1 second sleep") - Thread.currentThread().interrupt() - } - - challenge.update() - LOG.info(challenge.status.toString()) - } while (challenge.status == Status.PENDING) - if (challenge.status != Status.VALID) { - throw AcmeClientException("Failed to successfully solve challenge") + .authorizations + .parallelStream() + .map { authorization -> + authorization.findChallenge(Http01Challenge.TYPE) + } + .forEach { challenge -> + challengeMap[challenge.token] = challenge.authorization + try { + // solve the challenge + challenge.trigger() + do { + try { + Thread.sleep(1000L) + } catch (ie: InterruptedException) { + LOG.error("Error while doing 1 second sleep") + Thread.currentThread().interrupt() } - } catch (e: AcmeException) { - throw AcmeClientException(e) + + challenge.update() + LOG.info(challenge.status.toString()) + } while (challenge.status == Status.PENDING) + if (challenge.status != Status.VALID) { + throw AcmeClientException("Failed to successfully solve challenge") } + } catch (e: AcmeException) { + throw AcmeClientException(e) } + } } catch (e: AcmeException) { LOG.error("Error while placing certificate order", e) throw AcmeClientException(e) } - val timestamp = LocalDateTime.now().format(DateTimeFormatter - .ofPattern("yyyy-MM-dd_HH:mm:ss.SSS")) + val timestamp = + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH:mm:ss.SSS")) try { Files.newBufferedReader( - targetDirectory.resolve("domain.key"), StandardCharsets.UTF_8).use { keyReader -> - Files.newBufferedWriter( - targetDirectory.resolve("csr_ $timestamp.csr"), - StandardCharsets.UTF_8).use { csrWriter -> + targetDirectory.resolve("domain.key"), + StandardCharsets.UTF_8 + ) + .use { keyReader -> Files.newBufferedWriter( - targetDirectory.resolve("cert-chain_$timestamp.crt"), - StandardCharsets.UTF_8).use { chainWriter -> - val domainKeyPair = KeyPairUtils.readKeyPair(keyReader) + targetDirectory.resolve("csr_ $timestamp.csr"), + StandardCharsets.UTF_8 + ) + .use { csrWriter -> + Files.newBufferedWriter( + targetDirectory.resolve("cert-chain_$timestamp.crt"), + StandardCharsets.UTF_8 + ) + .use { chainWriter -> + val domainKeyPair = KeyPairUtils.readKeyPair(keyReader) - val csrb = CSRBuilder() - csrb.addDomains(*domains) - // TODO: Retrieve such information from settings/info-model - csrb.setOrganization("Trusted Connector") - csrb.sign(domainKeyPair) - csrb.write(csrWriter) - order.execute(csrb.encoded) + val csrb = CSRBuilder() + csrb.addDomains(*domains) + // TODO: Retrieve such information from settings/info-model + csrb.setOrganization("Trusted Connector") + csrb.sign(domainKeyPair) + csrb.write(csrWriter) + order.execute(csrb.encoded) - // Download and save certificate - val certificate = order.certificate - certificate!!.writeCertificate(chainWriter) - // Create JKS keystore from key and certificate chain - val keyStorePath = targetDirectory.resolve("keystore_$timestamp.jks") - try { - Files.newOutputStream(keyStorePath).use { jksOutputStream -> - val store = KeyStore.getInstance("JKS") - store.load(null) - store.setKeyEntry( - "ids", - domainKeyPair.private, - "ids".toCharArray(), - certificate.certificateChain.toTypedArray()) - store.store(jksOutputStream, "ids".toCharArray()) - // If there is a SslContextFactoryReloader, make it refresh the TLS connections. - LOG.info( - "Reloading of {} SslContextFactoryReloadable implementations...", - sslReloadables.size) - sslReloadables.forEach { r -> r.reload(keyStorePath.toString()) } - } - } catch (e: Exception) { - LOG.error("Error whilst creating new KeyStore!", e) - } + // Download and save certificate + val certificate = order.certificate + certificate!!.writeCertificate(chainWriter) + // Create PKCS12 keystore from key and certificate chain + val keyStorePath = + targetDirectory.resolve("keystore_$timestamp.p12") + try { + Files.newOutputStream(keyStorePath).use { ksOutputStream + -> + val store = KeyStore.getInstance("PKCS12") + store.load(null) + store.setKeyEntry( + "ids", + domainKeyPair.private, + "password".toCharArray(), + certificate.certificateChain.toTypedArray< + X509Certificate>() + ) + store.store( + ksOutputStream, + "password".toCharArray() + ) + // If there is a SslContextFactoryReloader, make it + // refresh the TLS connections. + LOG.info( + "Reloading of {} SslContextFactoryReloadable implementations...", + sslReloadables.size + ) + sslReloadables.forEach { r -> + r.reload(keyStorePath.toString()) + } + } + } catch (e: Exception) { + LOG.error("Error whilst creating new KeyStore!", e) + } - Files.copy( - keyStorePath, - targetDirectory.resolve(KEYSTORE_LATEST), - StandardCopyOption.REPLACE_EXISTING) - } + Files.copy( + keyStorePath, + targetDirectory.resolve(KEYSTORE_LATEST), + StandardCopyOption.REPLACE_EXISTING + ) + } + } } - } } catch (e: IOException) { LOG.error("Could not read ACME key pair", e) throw AcmeClientException(e) @@ -295,7 +320,6 @@ class AcmeClientService : AcmeClient, Runnable { LOG.error("Error while retrieving certificate", e) throw AcmeClientException(e) } - } catch (e: IOException) { LOG.error("Failed to start HTTP server", e) throw AcmeClientException(e) @@ -306,39 +330,56 @@ class AcmeClientService : AcmeClient, Runnable { } fun renewalCheck( - targetDirectory: Path, acmeServerUrl: String, domains: Array, challengePort: Int) { + targetDirectory: Path, + acmeServerUrl: String, + domains: Array, + challengePort: Int + ) { if (acmeServerUrl.isEmpty()) { LOG.info("ACME server URL is empty, skipping renewal check.") return } try { - Files.newInputStream(targetDirectory.resolve(KEYSTORE_LATEST)).use { jksInputStream -> - val store = KeyStore.getInstance("JKS") - store.load(jksInputStream, "ids".toCharArray()) + Files.newInputStream(targetDirectory.resolve(KEYSTORE_LATEST)).use { ksInputStream -> + val store = KeyStore.getInstance("PKCS12") + store.load(ksInputStream, "password".toCharArray()) val cert = store.getCertificateChain("ids")[0] as X509Certificate val now = Date().time val notBeforeTime = cert.notBefore.time val notAfterTime = cert.notAfter.time - val validityPercentile = 100.0 * (notAfterTime - now).toDouble() / + val validityPercentile = + 100.0 * (notAfterTime - now).toDouble() / (notAfterTime - notBeforeTime).toDouble() if (LOG.isInfoEnabled) { LOG.info( - String.format( - "Remaining relative validity span (%s): %.2f%%", - targetDirectory.toString(), validityPercentile)) + String.format( + "Remaining relative validity span (%s): %.2f%%", + targetDirectory.toString(), + validityPercentile + ) + ) } if (validityPercentile < RENEWAL_THRESHOLD) { if (LOG.isInfoEnabled) { LOG.info( - String.format( - "%.2f < %.2f, requesting renewal", - validityPercentile, RENEWAL_THRESHOLD)) + String.format( + "%.2f < %.2f, requesting renewal", + validityPercentile, + RENEWAL_THRESHOLD + ) + ) } - // Do the renewal in a separate Thread such that other stuff can be executed in parallel. - // This is especially important if the ACME protocol implementations are missing upon boot. + // Do the renewal in a separate Thread such that other stuff can be executed in + // parallel. + // This is especially important if the ACME protocol implementations are missing + // upon boot. val t = Thread { renewCertificate( - targetDirectory, URI.create(acmeServerUrl), domains, challengePort) + targetDirectory, + URI.create(acmeServerUrl), + domains, + challengePort + ) } t.name = "ACME Renewal Thread" t.isDaemon = true @@ -348,7 +389,6 @@ class AcmeClientService : AcmeClient, Runnable { } catch (e: Exception) { LOG.error("Error in web console keystore renewal check", e) } - } @Activate @@ -357,21 +397,25 @@ class AcmeClientService : AcmeClient, Runnable { try { val config = settings!!.connectorConfig renewalCheck( - FileSystems.getDefault().getPath("etc", "tls-webconsole"), - config.acmeServerWebcon, - config.acmeDnsWebcon.trim { it <= ' ' }.split("\\s*,\\s*".toRegex()) - .dropLastWhile { it.isEmpty() }.toTypedArray(), - config.acmePortWebcon) + FileSystems.getDefault().getPath("etc", "tls-webconsole"), + config.acmeServerWebcon, + config + .acmeDnsWebcon + .trim { it <= ' ' } + .split("\\s*,\\s*".toRegex()) + .dropLastWhile { it.isEmpty() } + .toTypedArray(), + config.acmePortWebcon + ) } catch (e: Exception) { LOG.error("ACME Renewal task failed", e) } - } companion object { const val RENEWAL_THRESHOLD = 100.0 / 3.0 - const val KEYSTORE_LATEST = "keystore_latest.jks" + const val KEYSTORE_LATEST = "keystore_latest.p12" private val LOG = LoggerFactory.getLogger(AcmeClientService::class.java)!! private val challengeMap = HashMap() } diff --git a/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/provider/BoulderAcmeProvider.kt b/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/provider/BoulderAcmeProvider.kt index 152caff99..50acfea23 100644 --- a/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/provider/BoulderAcmeProvider.kt +++ b/ids-acme/src/main/kotlin/de/fhg/aisec/ids/acme/provider/BoulderAcmeProvider.kt @@ -19,12 +19,12 @@ */ package de.fhg.aisec.ids.acme.provider -import org.shredzone.acme4j.provider.AbstractAcmeProvider -import org.shredzone.acme4j.provider.AcmeProvider import java.net.MalformedURLException import java.net.URI import java.net.URL import java.util.regex.Pattern +import org.shredzone.acme4j.provider.AbstractAcmeProvider +import org.shredzone.acme4j.provider.AcmeProvider /** * An [AcmeProvider] for *Boulder*. @@ -51,7 +51,6 @@ class BoulderAcmeProvider : AbstractAcmeProvider() { } catch (ex: MalformedURLException) { throw IllegalArgumentException("Bad server URI $serverUri", ex) } - } /** diff --git a/ids-api/build.gradle b/ids-api/build.gradle deleted file mode 100644 index 0130b565c..000000000 --- a/ids-api/build.gradle +++ /dev/null @@ -1,36 +0,0 @@ -version = libraryVersions.api - -apply plugin: 'com.google.protobuf' -apply plugin: 'idea' - -protobuf { - generatedFilesBaseDir = "$projectDir/generated" -} - -clean { - delete protobuf.generatedFilesBaseDir -} - -idea { - module { - // mark as generated sources for IDEA - generatedSourceDirs += file("${protobuf.generatedFilesBaseDir}/main/java") - } -} - -dependencies { - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - providedByBundle group: 'com.google.protobuf', name: 'protobuf-java', version: libraryVersions.protobuf - - providedByBundle group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: libraryVersions.jackson - - publishCompile group: 'org.checkerframework', name: 'checker-qual', version: libraryVersions.checkerQual - - // Actual implementation must be provided by ids-infomodel-manager - publishCompile group: 'de.fraunhofer.iais.eis.ids.infomodel', name: 'java', version: libraryVersions.infomodel - - testImplementation group: 'junit', name: 'junit', version: libraryVersions.junit4 - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito -} diff --git a/ids-api/build.gradle.kts b/ids-api/build.gradle.kts new file mode 100644 index 000000000..c9150b579 --- /dev/null +++ b/ids-api/build.gradle.kts @@ -0,0 +1,47 @@ +import com.google.protobuf.gradle.protobuf +import org.gradle.plugins.ide.idea.model.IdeaModel + +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map + +apply(plugin = "com.google.protobuf") +apply(plugin = "idea") + +val protobufGeneratedDir = "$projectDir/generated" + +protobuf { + generatedFilesBaseDir = protobufGeneratedDir +} + +tasks.clean { + doFirst { + delete(protobufGeneratedDir) + } + // Sometimes required to fix an error caused by a non-existing folder + doLast { + mkdir("${project.buildDir}/classes/kotlin/main") + } +} + +configure { + module { + // mark as generated sources for IDEA + generatedSourceDirs.add(File("${protobufGeneratedDir}/main/java")) + } +} + +dependencies { + providedByBundle("com.google.protobuf", "protobuf-java", libraryVersions["protobuf"]) + + providedByBundle("com.fasterxml.jackson.core", "jackson-annotations", libraryVersions["jackson"]) + + publishCompile("org.checkerframework", "checker-qual", libraryVersions["checkerQual"]) + + // Actual implementation must be provided by ids-infomodel-manager + publishCompile("de.fraunhofer.iais.eis.ids.infomodel", "java", libraryVersions["infomodel"]) + + publishCompile("org.apache.camel", "camel-core", libraryVersions["camel"]) + + testImplementation("junit", "junit", libraryVersions["junit4"]) + testImplementation("org.mockito", "mockito-core", libraryVersions["mockito"]) +} diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/cm/ApplicationContainer.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/cm/ApplicationContainer.java index 00c1fb61d..3d04e2d9a 100644 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/cm/ApplicationContainer.java +++ b/ids-api/src/main/java/de/fhg/aisec/ids/api/cm/ApplicationContainer.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -46,6 +47,9 @@ public class ApplicationContainer { private String signature; private String owner; private String image; + private String imageId; + private List imageDigests; + private List ipAddresses; // Portainer attributes: private Object repository; @@ -220,6 +224,30 @@ public void setImage(String image) { this.image = image; } + public String getImageId() { + return imageId; + } + + public void setImageId(String imageId) { + this.imageId = imageId; + } + + public List getImageDigests() { + return imageDigests; + } + + public void setImageDigests(List digests) { + this.imageDigests = digests; + } + + public List getIpAddresses() { + return ipAddresses; + } + + public void setIpAddresses(List ipAddresses) { + this.ipAddresses = ipAddresses; + } + public String getRegistry() { return registry; } diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/ConnectorProfile.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/ConnectorProfile.java index e1d5c0032..96ec04975 100644 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/ConnectorProfile.java +++ b/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/ConnectorProfile.java @@ -19,8 +19,9 @@ */ package de.fhg.aisec.ids.api.infomodel; -import de.fraunhofer.iais.eis.*; -import de.fraunhofer.iais.eis.util.PlainLiteral; +import de.fraunhofer.iais.eis.SecurityProfile; +import de.fraunhofer.iais.eis.util.TypedLiteral; + import java.io.Serializable; import java.net.URI; import java.util.List; @@ -32,10 +33,10 @@ public final class ConnectorProfile implements Serializable { private SecurityProfile securityProfile; private URI connectorUrl; private URI maintainerUrl; - private List connectorEntityNames; + private List connectorEntityNames; public ConnectorProfile() { - this.securityProfile = SecurityProfile.BASE_CONNECTOR_SECURITY_PROFILE; + this.securityProfile = SecurityProfile.TRUST_SECURITY_PROFILE; this.connectorUrl = null; this.maintainerUrl = null; this.connectorEntityNames = null; @@ -45,7 +46,7 @@ public ConnectorProfile( SecurityProfile profile, URI connectorUrl, URI maintainerUrl, - List connectorEntityNames) { + List connectorEntityNames) { super(); this.securityProfile = profile; this.connectorUrl = connectorUrl; @@ -65,7 +66,7 @@ public URI getMaintainerUrl() { return maintainerUrl; } - public List getConnectorEntityNames() { + public List getConnectorEntityNames() { return connectorEntityNames; } @@ -81,7 +82,7 @@ public void setMaintainerUrl(URI maintainerUrl) { this.maintainerUrl = maintainerUrl; } - public void setConnectorEntityNames(List connectorEntityNames) { + public void setConnectorEntityNames(List connectorEntityNames) { this.connectorEntityNames = connectorEntityNames; } } diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/InfoModel.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/InfoModel.java deleted file mode 100644 index 7e06bac3b..000000000 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/InfoModel.java +++ /dev/null @@ -1,74 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-api - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.api.infomodel; - -import de.fraunhofer.iais.eis.Connector; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -public interface InfoModel { - - /** - * Retrieve Connector object based on stored properties - * - * @return currently stored Connector object - */ - @Nullable - Connector getConnector(); - - /** - * Save/Update Connector object to preferences - * - * @param profile Basic connector profile from GUI - * @return update success - */ - boolean setConnector(@NonNull ConnectorProfile profile); - - /** - * Get connector self-description as JSON-LD - * - * @return Connector self-description as JSON-LD - */ - @NonNull - String getConnectorAsJsonLd(); - - /** - * Set static connector self-description as JSON-LD, or remove if "null" is passed - * - * @param jsonLd JSON-LD self-description to use for this connector - */ - void setConnectorByJsonLd(@Nullable String jsonLd); - - /** - * Get connector Dynamic Attribute Token - * - * @return DAT - */ - @NonNull - String getDynamicAttributeToken(); - - /** - * Set Dynamic Attribute Token or remove if "null" is passed - * - * @param dynamicAttributeToken The DAT to use for this connector - * @return Whether storing the DAT has been successful - */ - boolean setDynamicAttributeToken(@NonNull String dynamicAttributeToken); -} diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/InfoModel.kt b/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/InfoModel.kt new file mode 100644 index 000000000..e55d10672 --- /dev/null +++ b/ids-api/src/main/java/de/fhg/aisec/ids/api/infomodel/InfoModel.kt @@ -0,0 +1,60 @@ +/*- + * ========================LICENSE_START================================= + * ids-api + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.api.infomodel + +import de.fraunhofer.iais.eis.Connector + +interface InfoModel { + /** + * Retrieve Connector object based on stored properties + * + * @return currently stored Connector object + */ + val connector: Connector? + + /** + * Save/Update Connector object to preferences + * + * @param profile Basic connector profile from GUI + * @return update success + */ + fun setConnector(profile: ConnectorProfile): Boolean + + /** + * Get connector self-description as JSON-LD + * + * @return Connector self-description as JSON-LD + */ + val connectorAsJsonLd: String + + /** + * Set static connector self-description as JSON-LD, or remove if "null" is passed + * + * @param jsonLd JSON-LD self-description to use for this connector + */ + fun setConnectorByJsonLd(jsonLd: String?) + + /** + * Get version of implemented infomodel + * + * @return Version of infomodel + */ + val modelVersion: String +} diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/policy/DecisionRequest.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/policy/DecisionRequest.java index 89d7dcf20..56b90222e 100644 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/policy/DecisionRequest.java +++ b/ids-api/src/main/java/de/fhg/aisec/ids/api/policy/DecisionRequest.java @@ -19,11 +19,13 @@ */ package de.fhg.aisec.ids.api.policy; -import java.util.Map; -import java.util.Objects; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + /** * Data structure holding a decision request which is sent to the PDP. The PDP is expected to answer * with a PolicyDecision object. @@ -38,7 +40,7 @@ public class DecisionRequest { @NonNull private ServiceNode to; /** Properties of the message (e.g., labels) */ - @NonNull private Map msgCtx; + @NonNull private Set labels; /** Properties of the environment */ @Nullable private Map envCtx; @@ -46,12 +48,12 @@ public class DecisionRequest { public DecisionRequest( @NonNull ServiceNode from, @NonNull ServiceNode to, - @NonNull Map msgCtx, + @NonNull Set labels, @Nullable Map envCtx) { super(); this.from = from; this.to = to; - this.msgCtx = msgCtx; + this.labels = labels; this.envCtx = envCtx; } @@ -84,8 +86,8 @@ public ServiceNode getTo() { * @return Properties of the Exchange */ @NonNull - public Map getProperties() { - return msgCtx; + public Set getLabels() { + return labels; } /** @@ -109,12 +111,12 @@ public boolean equals(Object o) { DecisionRequest that = (DecisionRequest) o; return Objects.equals(from, that.from) && Objects.equals(to, that.to) - && Objects.equals(msgCtx, that.msgCtx) + && Objects.equals(labels, that.labels) && Objects.equals(envCtx, that.envCtx); } @Override public int hashCode() { - return Objects.hash(from, to, msgCtx, envCtx); + return Objects.hash(from, to, labels, envCtx); } } diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/policy/PDP.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/policy/PDP.java index 054a5c26b..20d523564 100644 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/policy/PDP.java +++ b/ids-api/src/main/java/de/fhg/aisec/ids/api/policy/PDP.java @@ -19,6 +19,8 @@ */ package de.fhg.aisec.ids.api.policy; +import org.checkerframework.checker.nullness.qual.NonNull; + /** * Policy Decision Point (PDP) Interface. * @@ -28,8 +30,6 @@ * @author Julian Schütte (julian.schuette@aisec.fraunhofer.de) */ public interface PDP { - String LABELS_KEY = "luconLabels"; - /** * Main method for requesting a policy decision. * @@ -39,6 +39,7 @@ public interface PDP { * @param req The decision request, wrapping relevant data for policy decision * @return The policy decision */ + @NonNull PolicyDecision requestDecision(DecisionRequest req); /** Removes all data from PDP-internal caches. Future decisions will possibly take more time. */ diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/router/RouteVerificationProof.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/router/RouteVerificationProof.java index 5f4d1ae8b..6ac70b6de 100644 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/router/RouteVerificationProof.java +++ b/ids-api/src/main/java/de/fhg/aisec/ids/api/router/RouteVerificationProof.java @@ -86,9 +86,8 @@ public String getQuery() { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("Proof for ").append(this.query).append("\n"); - sb.append("returns ").append(this.isValid).append("\n"); - sb.append("Example flows violating policy:\n"); + sb.append("Proof for ").append(this.query).append(" is ").append(this.isValid ? "VALID" : "INVALID").append("\n") + .append("Example flows violating policy:\n"); for (CounterExample ce : this.counterExamples) { sb.append("|-- ").append(ce.toString()).append("\n\n"); } diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/ConnectionSettings.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/ConnectionSettings.java index 92438d7fc..7c297b7be 100644 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/ConnectionSettings.java +++ b/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/ConnectionSettings.java @@ -24,55 +24,14 @@ public final class ConnectionSettings implements Serializable { private static final long serialVersionUID = 1L; - private final String integrityProtectionAndVerification; - private final String authentication; - private final String serviceIsolation; - private final String integrityProtectionVerificationScope; - private final String appExecutionResources; - private final String dataUsageControlSupport; - private final String auditLogging; - private final String localDataConfidentiality; + private final String securityProfile; public ConnectionSettings() { - integrityProtectionAndVerification = "1"; - authentication = "1"; - serviceIsolation = "1"; - integrityProtectionVerificationScope = "1"; - appExecutionResources = "1"; - dataUsageControlSupport = "1"; - auditLogging = "1"; - localDataConfidentiality = "1"; + securityProfile = "idsc:TRUSTED_CONNECTOR_SECURITY_PROFILE"; } - public String getIntegrityProtectionAndVerification() { - return integrityProtectionAndVerification; + public String getRequiredSecurityProfile() { + return securityProfile; } - public String getAuthentication() { - return authentication; - } - - public String getServiceIsolation() { - return serviceIsolation; - } - - public String getIntegrityProtectionVerificationScope() { - return integrityProtectionVerificationScope; - } - - public String getAppExecutionResources() { - return appExecutionResources; - } - - public String getDataUsageControlSupport() { - return dataUsageControlSupport; - } - - public String getAuditLogging() { - return auditLogging; - } - - public String getLocalDataConfidentiality() { - return localDataConfidentiality; - } } diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/ConnectorConfig.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/ConnectorConfig.java index a373bc7c8..4445cf458 100644 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/ConnectorConfig.java +++ b/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/ConnectorConfig.java @@ -37,7 +37,6 @@ public final class ConnectorConfig implements Serializable { private final String keystorePassword; private final String keystoreAliasName; private final String truststoreName; - private final String connectorUUID; public ConnectorConfig() { appstoreUrl = @@ -49,12 +48,11 @@ public ConnectorConfig() { acmeDnsWebcon = ""; acmePortWebcon = 80; tosAcceptWebcon = false; - dapsUrl = "http://daps.aisec.fraunhofer.de/token"; - keystoreName = "client-keystore.jks"; + dapsUrl = "https://daps.aisec.fraunhofer.de"; + keystoreName = "provider-keystore.p12"; keystorePassword = "password"; keystoreAliasName = "1"; - truststoreName = "client-truststore.jks"; - connectorUUID = "00c6155a-966d-4d2c-af6e-60f997e24da2"; + truststoreName = "truststore.p12"; } public String getAppstoreUrl() { @@ -109,7 +107,4 @@ public String getTruststoreName() { return truststoreName; } - public String getConnectorUUID() { - return connectorUUID; - } } diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/Settings.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/Settings.java index 053674ee1..a1ef03180 100644 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/Settings.java +++ b/ids-api/src/main/java/de/fhg/aisec/ids/api/settings/Settings.java @@ -20,6 +20,7 @@ package de.fhg.aisec.ids.api.settings; import de.fhg.aisec.ids.api.infomodel.ConnectorProfile; + import java.util.Map; public interface Settings { @@ -36,10 +37,6 @@ public interface Settings { void setConnectorJsonLd(String jsonLd); - String getDynamicAttributeToken(); - - void setDynamicAttributeToken(String dynamicAttributeToken); - ConnectionSettings getConnectionSettings(String connection); void setConnectionSettings(String connection, ConnectionSettings connectionSettings); diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/DatException.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/DatException.java deleted file mode 100644 index 241503ade..000000000 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/DatException.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.fhg.aisec.ids.api.tokenm; - -public class DatException extends Exception { - public DatException(String message) { - super(message); - } - - public DatException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/TokenManager.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/TokenManager.java deleted file mode 100755 index d0ecadc5c..000000000 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/TokenManager.java +++ /dev/null @@ -1,55 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-api - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.api.tokenm; - -import de.fhg.aisec.ids.api.settings.ConnectionSettings; - -import java.nio.file.Path; -import java.util.Map; - -/** - * Interface of the Token Manager. - * - *

TThe Token Manager takes care of identity tokens (such as the Dynamic Attribute Token, - * acquired by the Dynamic Attribute Provisioning Service. - * - * @author Gerd Brost (gerd.brost@aisec.fraunhofer.de) - */ -public interface TokenManager { - - Map acquireToken( - Path targetDirectory, - String dapsUrl, - String keyStoreName, - String keyStorePassword, - String keystoreAliasName, - String trustStoreName, - String connectorUUID); - - Map verifyJWT( - String dynamicAttributeToken, - String targetAudience, - String dapsUrl) throws Exception; - - void validateDATSecurityAttributes( - Map claims, - ConnectionSettings connectionSettings) throws DatException; - -} diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/package-info.java b/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/package-info.java deleted file mode 100755 index 9bb42794e..000000000 --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/package-info.java +++ /dev/null @@ -1,21 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * IDS Core Platform API - * %% - * Copyright (C) 2017 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -/** APIs for accessing token services. */ -package de.fhg.aisec.ids.api.tokenm; diff --git a/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/DynamicAttributeToken.java b/ids-api/src/main/kotlin/de/fhg/aisec/ids/api/ExtensionFunctions.kt old mode 100755 new mode 100644 similarity index 54% rename from ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/DynamicAttributeToken.java rename to ids-api/src/main/kotlin/de/fhg/aisec/ids/api/ExtensionFunctions.kt index 339fe6a9b..63c1f131c --- a/ids-api/src/main/java/de/fhg/aisec/ids/api/tokenm/DynamicAttributeToken.java +++ b/ids-api/src/main/kotlin/de/fhg/aisec/ids/api/ExtensionFunctions.kt @@ -2,7 +2,7 @@ * ========================LICENSE_START================================= * ids-api * %% - * Copyright (C) 2019 Fraunhofer AISEC + * Copyright (C) 2021 Fraunhofer AISEC * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,21 +17,23 @@ * limitations under the License. * =========================LICENSE_END================================== */ -package de.fhg.aisec.ids.api.tokenm; +package de.fhg.aisec.ids.api -/** - * Dynamic Attribute Token. Wraps the token acquired from the DAPS. - * - * @author Gerd Brost (gerd.brost@aisec.fraunhofer.de) - */ -public final class DynamicAttributeToken { - final String token; - - public DynamicAttributeToken(String token) { - this.token = token; - } +import java.io.IOException +import java.util.concurrent.TimeUnit - public String getToken() { - return token; - } +fun String.runCommand(): String? { + return try { + val parts = this.split("\\s".toRegex()) + val proc = + ProcessBuilder(*parts.toTypedArray()) + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .redirectError(ProcessBuilder.Redirect.PIPE) + .start() + proc.waitFor(10, TimeUnit.SECONDS) + proc.inputStream.bufferedReader().readText() + } catch (e: IOException) { + e.printStackTrace() + null + } } diff --git a/ids-api/src/main/kotlin/de/fhg/aisec/ids/api/idscp2/Idscp2UsageControlInterface.kt b/ids-api/src/main/kotlin/de/fhg/aisec/ids/api/idscp2/Idscp2UsageControlInterface.kt new file mode 100644 index 000000000..37d7e6e62 --- /dev/null +++ b/ids-api/src/main/kotlin/de/fhg/aisec/ids/api/idscp2/Idscp2UsageControlInterface.kt @@ -0,0 +1,43 @@ +/*- + * ========================LICENSE_START================================= + * ids-api + * %% + * Copyright (C) 2021 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.api.idscp2 + +import de.fraunhofer.iais.eis.ContractAgreement +import java.net.URI +import org.apache.camel.Exchange + +/** + * This interface has to be parameterized with the type of the connection objects handled, e.g. + * AppLayerConnection objects. This avoids the necessity of library dependencies to the module + * defining this class. + */ +interface Idscp2UsageControlInterface { + /** + * Provides the (Idscp2)Connection object that is linked with the Apache Camel Consumer which + * created the particular Exchange object. + */ + fun getExchangeContract(exchange: Exchange): ContractAgreement? + + fun isProtected(exchange: Exchange): Boolean + + fun protectBody(exchange: Exchange, contractUri: URI) + + fun unprotectBody(exchange: Exchange) +} diff --git a/ids-comm/.gitignore b/ids-comm/.gitignore deleted file mode 100644 index 180f3422a..000000000 --- a/ids-comm/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/target/ -/bin/ -/generated/ -configuration.db -/cp.txt -*.pyc -/.classpath -/build.properties diff --git a/ids-comm/LICENSE.txt b/ids-comm/LICENSE.txt deleted file mode 100644 index 261eeb9e9..000000000 --- a/ids-comm/LICENSE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/ids-comm/README.md b/ids-comm/README.md deleted file mode 100644 index 990171e66..000000000 --- a/ids-comm/README.md +++ /dev/null @@ -1 +0,0 @@ -The _ids-comm_ module wraps the IDSCP, providing secure communication and remote attestation between Connector instances. diff --git a/ids-comm/bnd.bnd b/ids-comm/bnd.bnd deleted file mode 100644 index 379857898..000000000 --- a/ids-comm/bnd.bnd +++ /dev/null @@ -1,7 +0,0 @@ -Bundle-Name: IDS :: IDS Communication Protocol -Bundle-Description: IDS Communication Protocol -Export-Package: \ - de.fhg.aisec.ids.comm* -Import-Package: \ - !org.checkerframework.checker*,\ - * \ No newline at end of file diff --git a/ids-comm/build.gradle b/ids-comm/build.gradle deleted file mode 100644 index fc9afa8b9..000000000 --- a/ids-comm/build.gradle +++ /dev/null @@ -1,25 +0,0 @@ -version = libraryVersions.idscp - -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - - providedByBundle(group: 'com.github.microsoft', name: 'TSS.Java', version: libraryVersions.tssJava) { - // JNA not needed, because we do not directly communicate with the TPM via this library - exclude group: 'net.java.dev.jna', module: 'jna' - } - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - providedByBundle group: 'com.google.protobuf', name: 'protobuf-java', version: libraryVersions.protobuf - - publishCompile group: 'org.checkerframework', name: 'checker-qual', version: libraryVersions.checkerQual - - providedByBundle group: 'org.asynchttpclient', name: 'async-http-client', version: libraryVersions.ahc - - providedByFeature group: 'org.eclipse.jetty.websocket', name: 'websocket-server', version: libraryVersions.jetty - providedByFeature group: 'org.eclipse.jetty.websocket', name: 'websocket-client', version: libraryVersions.jetty - - testImplementation group: 'junit', name: 'junit', version: libraryVersions.junit4 - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito -} diff --git a/ids-comm/socket/.gitignore b/ids-comm/socket/.gitignore deleted file mode 100644 index c74d68277..000000000 --- a/ids-comm/socket/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.sock diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ByteArrayUtil.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ByteArrayUtil.java deleted file mode 100644 index 689951053..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ByteArrayUtil.java +++ /dev/null @@ -1,48 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm; - -public class ByteArrayUtil { - - private static final String[] lookup = new String[256]; - - static { - for (int i = 0; i < lookup.length; ++i) { - if (i < 16) { - lookup[i] = "0" + Integer.toHexString(i); - } else { - lookup[i] = Integer.toHexString(i); - } - } - } - - public static String toPrintableHexString(byte[] bytes) { - StringBuilder s = new StringBuilder(); - for (int i = 0; i < bytes.length; ++i) { - if (i > 0 && i % 16 == 0) { - s.append('\n'); - } else { - s.append(' '); - } - s.append(lookup[bytes[i] & 0xff]); - } - return s.toString(); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/CertificatePair.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/CertificatePair.java deleted file mode 100644 index 043632388..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/CertificatePair.java +++ /dev/null @@ -1,51 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm; - -import java.security.cert.Certificate; - -public class CertificatePair { - - private Certificate localCertificate = null; - private Certificate remoteCertificate = null; - - public CertificatePair() {} - - public CertificatePair(CertificatePair certificatePair) { - this.localCertificate = certificatePair.localCertificate; - this.remoteCertificate = certificatePair.remoteCertificate; - } - - public Certificate getLocalCertificate() { - return localCertificate; - } - - public void setLocalCertificate(Certificate localCertificate) { - this.localCertificate = localCertificate; - } - - public Certificate getRemoteCertificate() { - return remoteCertificate; - } - - public void setRemoteCertificate(Certificate remoteCertificate) { - this.remoteCertificate = remoteCertificate; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/DatVerifier.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/DatVerifier.java deleted file mode 100644 index 9c3e032f3..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/DatVerifier.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.fhg.aisec.ids.comm; - -import de.fhg.aisec.ids.api.tokenm.DatException; - -@FunctionalInterface -public interface DatVerifier { - void verify(String dat) throws DatException; -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/IdscpConfiguration.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/IdscpConfiguration.java deleted file mode 100644 index efcb611f5..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/IdscpConfiguration.java +++ /dev/null @@ -1,33 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm; - -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import java.net.URI; - -public interface IdscpConfiguration { - IdsAttestationType getAttestationType(); - - int getAttestationMask(); - - CertificatePair getCertificatePair(); - - URI getTrustedThirdPartyURI(); -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/client/ClientConfiguration.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/client/ClientConfiguration.java deleted file mode 100644 index 09136d367..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/client/ClientConfiguration.java +++ /dev/null @@ -1,140 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.client; - -import de.fhg.aisec.ids.comm.CertificatePair; -import de.fhg.aisec.ids.comm.IdscpConfiguration; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import java.net.URI; -import java.util.Collections; -import java.util.List; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** - * Configuration of a client-side (Consumer) IDSC endpoint. - * - * @author Julian Schütte (julian.schuette@aisec.fraunhofer.de) - */ -public class ClientConfiguration implements IdscpConfiguration { - @NonNull private IdsAttestationType attestationType = IdsAttestationType.BASIC; - private int attestationMask = 0; - @NonNull private CertificatePair certificatePair = new CertificatePair(); - @NonNull private String rdfDescription = ""; - @NonNull private String dynamicAttributeToken = ""; - @NonNull private String endpoint = ""; - @NonNull private List sha256CertificateHashes = Collections.emptyList(); - @Nullable protected URI ttpUri; - - public static class Builder { - @NonNull private ClientConfiguration config = new ClientConfiguration(); - - public Builder attestationMask(int attestationMask) { - config.attestationMask = attestationMask; - return this; - } - - @NonNull - public Builder attestationType(@NonNull IdsAttestationType attestationType) { - config.attestationType = attestationType; - return this; - } - - @NonNull - public Builder certificatePair(@NonNull CertificatePair certificatePair) { - config.certificatePair = certificatePair; - return this; - } - - @NonNull - public Builder ttpUrl(@NonNull URI ttpUri) { - config.ttpUri = ttpUri; - return this; - } - - @NonNull - public Builder rdfDescription(@NonNull String rdfDescription) { - config.rdfDescription = rdfDescription; - return this; - } - - @NonNull - public Builder dynamicAttributeToken(@NonNull String dynamicAttributeToken) { - config.dynamicAttributeToken = dynamicAttributeToken; - return this; - } - - @NonNull - public Builder endpoint(@NonNull String endpoint) { - config.endpoint = endpoint; - return this; - } - - @NonNull - public Builder setSha256CertificateHashes(@NonNull List hashes) { - config.sha256CertificateHashes = hashes; - return this; - } - - @NonNull - public ClientConfiguration build() { - return config; - } - } - - @NonNull - public IdsAttestationType getAttestationType() { - return attestationType; - } - - public int getAttestationMask() { - return attestationMask; - } - - @NonNull - public CertificatePair getCertificatePair() { - return certificatePair; - } - - @NonNull - public String getDynamicAttributeToken() { - return dynamicAttributeToken; - } - - @NonNull - public String getRDFDescription() { - return rdfDescription; - } - - @Nullable - public URI getTrustedThirdPartyURI() { - return ttpUri; - } - - @NonNull - public String getEndpoint() { - return endpoint; - } - - @NonNull - public List getSha256CertificateHashes() { - return sha256CertificateHashes; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/client/IdscpClient.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/client/IdscpClient.java deleted file mode 100644 index 53cf8634f..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/client/IdscpClient.java +++ /dev/null @@ -1,179 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.client; - -import static org.asynchttpclient.Dsl.asyncHttpClient; - -import de.fhg.aisec.ids.api.conm.RatResult; -import io.netty.handler.ssl.ClientAuth; -import io.netty.handler.ssl.JdkSslContext; -import io.netty.handler.ssl.SslContext; -import java.net.URI; -import java.security.KeyManagementException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.concurrent.ExecutionException; -import javax.net.ssl.SSLContext; -import javax.net.ssl.X509TrustManager; -import javax.xml.bind.DatatypeConverter; -import org.asynchttpclient.AsyncHttpClient; -import org.asynchttpclient.DefaultAsyncHttpClientConfig.Builder; -import org.asynchttpclient.ws.WebSocket; -import org.asynchttpclient.ws.WebSocketUpgradeHandler; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -/** - * A standalone client implementation for the IDSCP protocol. - * - *

Simply call connect() and use the returned WebSocket object for bidirectional - * text/binary web socket communication with the remote endpoint. - * - *

Make sure to check handleAttestationResult() and getMetaData() to - * assess trustworthiness of the remote endpoint and the self description returned by it. - */ -public class IdscpClient { - - private ClientConfiguration config = new ClientConfiguration(); - private RatResult attestationResult = null; - private String metaData = null; - - /** - * Connects to a remote endpoint, executes the IDSCP handshake and returns the ready-to-use - * WebSocket object. - * - * @throws NoSuchAlgorithmException Use connect(String host, int port) instead. - */ - @Deprecated - public WebSocket connect(URI uri) - throws InterruptedException, ExecutionException, KeyManagementException, - NoSuchAlgorithmException { - return connect(uri.getHost(), uri.getPort()); - } - - /** - * Connects to a remote endpoint, executes the IDSCP handshake and returns the ready-to-use - * WebSocket object. - */ - public WebSocket connect(@NonNull String host, int port) - throws InterruptedException, ExecutionException, KeyManagementException, - NoSuchAlgorithmException { - final Builder builder = new Builder(); - if (!this.config.getSha256CertificateHashes().isEmpty()) { - SSLContext ctx = SSLContext.getInstance("TLS"); - ctx.init( - null, - new X509TrustManager[] { - new X509TrustManager() { - @Override - public void checkServerTrusted(X509Certificate[] certs, String str) - throws CertificateException { - try { - MessageDigest digest = MessageDigest.getInstance("SHA-256"); - byte[] digestBytes = digest.digest(certs[0].getEncoded()); - if (config - .getSha256CertificateHashes() - .stream() - .noneMatch(hash -> Arrays.equals(digestBytes, hash))) { - throw new CertificateException( - "Did not find pinned SHA256 certificate hash: " - + DatatypeConverter.printHexBinary(digestBytes)); - } - } catch (Exception x) { - throw new CertificateException("Error during hash calculation", x); - } - } - - @Override - public void checkClientTrusted(X509Certificate[] certs, String str) - throws CertificateException { - throw new CertificateException("Must not be called by client implementation!"); - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - } - }, - null); - SslContext sslContext = new JdkSslContext(ctx, true, ClientAuth.NONE); - builder.setSslContext(sslContext); - } - final AsyncHttpClient c = asyncHttpClient(builder.build()); - - // Connect to web socket - IdspClientSocket wsListener = new IdspClientSocket(this.config); - - WebSocket ws = - c.prepareGet("wss://" + host + ":" + port + "/" + this.config.getEndpoint()) - .execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(wsListener).build()) - .get(); - - // Block until ISCP has finished - wsListener.semaphore().lockInterruptibly(); - try { - while (!wsListener.isTerminated()) { - wsListener.idscpInProgressCondition().await(); - } - } finally { - this.attestationResult = wsListener.getAttestationResult(); - this.metaData = wsListener.getMetaResult(); - wsListener.semaphore().unlock(); - } - return ws; - } - - /** - * Sets the configuration of this client. - * - *

Use this method in a fluent API style before calling connect(): - * - *

-   * new IdscpClient().config(config).connect(url);
-   * 
- */ - @NonNull - public IdscpClient config(@NonNull ClientConfiguration config) { - this.config = config; - return this; - } - - /** - * Returns null if attestation has not yet finished, or status code of remote attestation - * otherwise. - */ - @Nullable - public RatResult getAttestationResult() { - return this.attestationResult; - } - - /** - * Returns meta data about the remote endpoint or null if no meta data has been - * exchanged. - */ - @Nullable - public String getMetaData() { - return this.metaData; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/client/IdspClientSocket.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/client/IdspClientSocket.java deleted file mode 100644 index 41c1d538b..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/client/IdspClientSocket.java +++ /dev/null @@ -1,145 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.client; - -import com.google.protobuf.InvalidProtocolBufferException; -import de.fhg.aisec.ids.api.conm.RatResult; -import de.fhg.aisec.ids.comm.DatVerifier; -import de.fhg.aisec.ids.comm.ws.protocol.ClientProtocolMachine; -import de.fhg.aisec.ids.comm.ws.protocol.ProtocolState; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.FSM; -import de.fhg.aisec.ids.messages.Idscp; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; -import org.asynchttpclient.ws.WebSocket; -import org.asynchttpclient.ws.WebSocketListener; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class IdspClientSocket implements WebSocketListener { - private static final Logger LOG = LoggerFactory.getLogger(IdspClientSocket.class); - private FSM fsm; - @NonNull private final ReentrantLock lock = new ReentrantLock(); - private final Condition idscpInProgress = lock.newCondition(); - private final ConnectorMessage startMsg = - Idscp.ConnectorMessage.newBuilder() - .setType(ConnectorMessage.Type.RAT_START) - .setId(new java.util.Random().nextLong()) - .build(); - private ClientConfiguration config; - private boolean isTerminated = false; - private DatVerifier datVerifier = dat -> { - if (LOG.isInfoEnabled()) { - LOG.info("Received DAT token: {}", dat); - } - }; - - public IdspClientSocket(ClientConfiguration config) { - this.config = config; - } - - public void setDatVerifier(DatVerifier datVerifier) { - this.datVerifier = datVerifier; - } - - @Override - public void onOpen(WebSocket websocket) { - LOG.debug("Websocket opened"); - - // create Finite State Machine for IDS protocol - this.fsm = new ClientProtocolMachine(websocket, this.config, this.datVerifier); - // start the protocol with the first message - this.fsm.feedEvent(new Event(startMsg.getType(), startMsg.toString(), startMsg)); - } - - @Override - public void onClose(WebSocket websocket, int code, String status) { - LOG.debug("websocket closed - reconnecting"); - fsm.reset(); - } - - @Override - public void onError(Throwable t) { - LOG.debug("websocket on error", t); - if (fsm != null) { - fsm.reset(); - } - } - - @Override - public void onBinaryFrame(byte[] message, boolean finalFragment, int rsv) { - LOG.debug("Client websocket received binary message {}", new String(message)); - try { - lock.lockInterruptibly(); - try { - ConnectorMessage msg = ConnectorMessage.parseFrom(message); - LOG.debug("Received in state " + fsm.getState() + ": " + new String(message)); - fsm.feedEvent(new Event(msg.getType(), new String(message), msg)); - } catch (InvalidProtocolBufferException e) { - LOG.error(e.getMessage(), e); - } - if (fsm.getState().equals(ProtocolState.IDSCP_END.id())) { - LOG.debug("Client is now terminating IDSCP"); - this.isTerminated = true; - idscpInProgress.signalAll(); - } - } catch (InterruptedException e) { - LOG.warn(e.getMessage()); - Thread.currentThread().interrupt(); - } finally { - lock.unlock(); - this.isTerminated = true; - } - } - - @Override - public void onTextFrame(String message, boolean finalFragment, int rsv) { - LOG.debug("Client websocket received text message {}", message); - onBinaryFrame(message.getBytes(), finalFragment, rsv); - } - - @NonNull - public ReentrantLock semaphore() { - return lock; - } - - @NonNull - public Condition idscpInProgressCondition() { - return idscpInProgress; - } - - public boolean isTerminated() { - return this.isTerminated; - } - - // get the result of the remote attestation - @NonNull - public RatResult getAttestationResult() { - return fsm.getRatResult(); - } - - @NonNull - public String getMetaResult() { - return fsm.getMetaData(); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/IdscpServer.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/IdscpServer.java deleted file mode 100644 index 7da134a99..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/IdscpServer.java +++ /dev/null @@ -1,123 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.server; - -import org.eclipse.jetty.server.*; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A standalone server implementation for the IDSCP protocol. - * - *

Simply call start() and use the registered SocketListener to - * handling incoming WebSocket connections. - * - *

Make sure to check handleAttestationResult() and getMetaData() to - * assess trustworthiness of the remote endpoint and the self description returned by it. - */ -public class IdscpServer { - private static final Logger LOG = LoggerFactory.getLogger(IdscpServer.class); - - private ServerConfiguration config = new ServerConfiguration(); - private Server server; - private SocketListener socketListener; - - public IdscpServer config(ServerConfiguration config) { - this.config = config; - return this; - } - - public IdscpServer setSocketListener(SocketListener socketListener) { - this.socketListener = socketListener; - return this; - } - - public IdscpServer start() { - Server s = new Server(); - HttpConfiguration https = new HttpConfiguration(); - https.addCustomizer(new SecureRequestCustomizer()); - - SslContextFactory sslContextFactory = new SslContextFactory.Server(); - sslContextFactory.setKeyStore(config.getKeyStore()); - sslContextFactory.setKeyStorePassword(this.config.getKeyStorePassword()); - sslContextFactory.setCertAlias(this.config.getCertAlias()); - sslContextFactory.setKeyManagerPassword(this.config.getKeyManagerPassword()); - - ServerConnector sslConnector = - new ServerConnector(s, sslContextFactory, new HttpConnectionFactory(https)); - sslConnector.setPort(this.config.getPort()); - s.setConnectors(new Connector[] {sslConnector}); - - // Setup the basic application "context" for this application at "/" - // This is also known as the handler tree (in jetty speak) - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - s.setHandler(context); - - // Add a websocket to a specific path spec - ServletHolder holderEvents = - new ServletHolder("ids", new ServerSocketServlet(this.config, this.socketListener)); - context.addServlet(holderEvents, "/"); - - try { - s.start(); - this.server = s; - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } - - return this; - } - - /** - * Adds a ServletContextHandler to a (possibly running) server. - * - * @return Adds an IDSCP servlet to this server - */ - public IdscpServer addServlet(String basePath) { - // TODO There should be one server per host/port, which is started at the first call to start(). - // This method should be removed and instead start() should register new basePaths, if necessary - if (this.server == null) { - throw new IllegalArgumentException("Wrong order: must call start() before addServlet()"); - } - - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - this.server.setHandler(context); - - // Add a websocket to a specific path spec - ServletHolder holderEvents = - new ServletHolder("ids", new ServerSocketServlet(this.config, this.socketListener)); - context.addServlet(holderEvents, basePath); - return this; - } - - public Server getServer() { - return this.server; - } - - public boolean isRunning() { - Server s = this.server; - return s != null && s.isRunning(); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/IdscpServerSocket.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/IdscpServerSocket.java deleted file mode 100644 index ae444112c..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/IdscpServerSocket.java +++ /dev/null @@ -1,168 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.server; - -import com.google.protobuf.InvalidProtocolBufferException; -import de.fhg.aisec.ids.api.conm.RatResult; -import de.fhg.aisec.ids.comm.DatVerifier; -import de.fhg.aisec.ids.comm.ws.protocol.ProtocolState; -import de.fhg.aisec.ids.comm.ws.protocol.ServerProtocolMachine; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.FSM; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.annotations.*; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Handles messages for the IDS protocol. - * - *

Messages from and to the web socket are connected to the FSM implementing the actual protocol. - * - * @author Julian Schütte (julian.schuette@aisec.fraunhofer.de) - */ -@WebSocket -public class IdscpServerSocket { - private static final Logger LOG = LoggerFactory.getLogger(IdscpServerSocket.class); - private FSM fsm; - private final ReentrantLock lock = new ReentrantLock(); - private final Condition isFinishedCond = lock.newCondition(); - - private ServerConfiguration config; - private SocketListener socketListener; - private Session session; - private DatVerifier datVerifier = dat -> { - if (LOG.isInfoEnabled()) { - LOG.info("Received DAT token: {}", dat); - } - }; - - public IdscpServerSocket(ServerConfiguration config, SocketListener socketListener) { - // Create provider socket - this.config = config; - this.socketListener = socketListener; - } - - public void setDatVerifier(DatVerifier datVerifier) { - this.datVerifier = datVerifier; - } - - /** - * Called upon incoming connection to server. - * - * @param session - */ - @OnWebSocketConnect - public void onOpen(Session session) { - if (LOG.isDebugEnabled()) { - LOG.debug( - "Websocket opened {} from {} to {}", - this, - session.getRemoteAddress(), - session.getLocalAddress()); - } - - this.session = session; - - // create Finite State Machine for IDS protocol - fsm = new ServerProtocolMachine(session, this.config, this.datVerifier); - } - - @OnWebSocketClose - public void onClose(Session session, int statusCode, String reason) { - LOG.debug("websocket closed"); - fsm.reset(); - socketListener.notifyClosed(this); - } - - @OnWebSocketError - public void onError(Throwable t) { - LOG.debug("websocket on error", t); - if (fsm != null) { - fsm.reset(); - } - } - - /** - * Handles incoming messages to server. - * - * @param session - * @param frame - */ - @OnWebSocketFrame - public void onMessage(Session session, Frame frame) { - byte[] message = new byte[frame.getPayload().remaining()]; - frame.getPayload().get(message); - LOG.debug("Received in state " + fsm.getState() + ": " + new String(message)); - try { - lock.lockInterruptibly(); - try { - if (fsm.getState().equals(ProtocolState.IDSCP_END.id()) - || fsm.getState().equals(ProtocolState.IDSCP_ERROR.id())) { - - LOG.debug("Passing through to web socket " + new String(message)); - if (this.socketListener != null) { - this.socketListener.onMessage(session, message); - } - return; - } - ConnectorMessage msg = ConnectorMessage.parseFrom(message); - fsm.feedEvent(new Event(msg.getType(), new String(message), msg)); - } catch (InvalidProtocolBufferException e) { - LOG.error(e.getMessage() + ": " + new String(message), e); - fsm.feedEvent( - new Event( - ConnectorMessage.Type.ERROR, - e.getMessage(), - ConnectorMessage.getDefaultInstance())); - } - } catch (InterruptedException e) { - LOG.warn(e.getMessage()); - Thread.currentThread().interrupt(); - } finally { - lock.unlock(); - } - } - - public ReentrantLock semaphore() { - return lock; - } - - public Condition isFinished() { - return isFinishedCond; - } - - // get the result of the remote attestation - public RatResult getAttestationResult() { - return fsm.getRatResult(); - } - - public String getMetaData() { - return fsm.getMetaData(); - } - - public Session getSession() { - return this.session; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/IdscpWebSocketCreator.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/IdscpWebSocketCreator.java deleted file mode 100644 index f25f71317..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/IdscpWebSocketCreator.java +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.server; - -import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; -import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; -import org.eclipse.jetty.websocket.servlet.WebSocketCreator; - -/** Creates a configurable WebSocket for the IDSCP protocol. */ -public class IdscpWebSocketCreator implements WebSocketCreator { - private ServerConfiguration config; - private SocketListener socketListener; - - public IdscpWebSocketCreator(ServerConfiguration config, SocketListener socketListener) { - this.config = config; - this.socketListener = socketListener; - } - - @Override - public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) { - return new IdscpServerSocket(this.config, this.socketListener); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/ServerConfiguration.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/ServerConfiguration.java deleted file mode 100644 index df4943ec3..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/ServerConfiguration.java +++ /dev/null @@ -1,179 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.server; - -import de.fhg.aisec.ids.comm.CertificatePair; -import de.fhg.aisec.ids.comm.IdscpConfiguration; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.net.URI; -import java.security.KeyStore; - -/** - * Configuration of the server-side (Provider) part of the IDSC protocol. - * - * @author Julian Schuette - * @author Gerd Brost - */ -public class ServerConfiguration implements IdscpConfiguration { - public static final int DEFAULT_PORT = 8080; - - private int port = DEFAULT_PORT; - @NonNull private IdsAttestationType attestationType = IdsAttestationType.BASIC; - private int attestationMask; - @NonNull private CertificatePair certificatePair = new CertificatePair(); - @Nullable private KeyStore keyStore = null; - @NonNull String rdfDescription = ""; - @NonNull String dynamicAttributeToken = ""; - @Nullable private URI ttpUri = null; - @NonNull private String keyStorePassword = "password"; - @NonNull private String keyManagerPassword = "password"; - @NonNull private String certAlias = "1"; - - public static class Builder { - @NonNull private ServerConfiguration config = new ServerConfiguration(); - - @NonNull - public Builder port(int port) { - config.port = port; - return this; - } - - @NonNull - public Builder attestationType(@NonNull IdsAttestationType attestationType) { - config.attestationType = attestationType; - return this; - } - - @NonNull - public Builder attestationMask(int attestationMask) { - config.attestationMask = attestationMask; - return this; - } - - @NonNull - public Builder certificatePair(@NonNull CertificatePair certificatePair) { - config.certificatePair = certificatePair; - return this; - } - - @NonNull - public Builder rdfDescription(@NonNull String rdfDescription) { - config.rdfDescription = rdfDescription; - return this; - } - - @NonNull - public Builder dynamicAttributeToken(@NonNull String dynamicAttributeToken) { - config.dynamicAttributeToken = dynamicAttributeToken; - return this; - } - - @NonNull - public Builder ttpUrl(@Nullable URI ttpUri) { - config.ttpUri = ttpUri; - return this; - } - - @NonNull - public Builder setKeyStore(@NonNull KeyStore keyStore) { - config.keyStore = keyStore; - return this; - } - - @NonNull - public Builder setKeyStorePassword(@NonNull String keyStorePassword) { - config.keyStorePassword = keyStorePassword; - return this; - } - - @NonNull - public Builder setKeyPassword(@NonNull String keyPassword) { - config.keyManagerPassword = keyPassword; - return this; - } - - @NonNull - public Builder setCertAlias(@NonNull String certAlias) { - config.certAlias = certAlias; - return this; - } - - @NonNull - public ServerConfiguration build() { - return config; - } - } - - public int getPort() { - return port; - } - - @NonNull - public IdsAttestationType getAttestationType() { - return attestationType; - } - - public int getAttestationMask() { - return attestationMask; - } - - @NonNull - public CertificatePair getCertificatePair() { - return certificatePair; - } - - @NonNull - public String getRDFDescription() { - return rdfDescription; - } - - @NonNull - public String getDynamicAttributeToken() { - return dynamicAttributeToken; - } - - @Nullable - public URI getTrustedThirdPartyURI() { - return ttpUri; - } - - @Nullable - public KeyStore getKeyStore() { - return keyStore; - } - - @NonNull - public String getKeyStorePassword() { - return keyStorePassword; - } - - @NonNull - public String getKeyManagerPassword() { - return keyManagerPassword; - } - - @NonNull - public String getCertAlias() { - return certAlias; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/ServerSocketServlet.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/ServerSocketServlet.java deleted file mode 100644 index 76233b72d..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/ServerSocketServlet.java +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.server; - -import org.eclipse.jetty.websocket.servlet.WebSocketServlet; -import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; - -public class ServerSocketServlet extends WebSocketServlet { - private static final long serialVersionUID = -3504454673920877370L; - private final ServerConfiguration config; - private SocketListener socketListener; - - public ServerSocketServlet(ServerConfiguration config, SocketListener socketListener) { - this.config = config; - this.socketListener = socketListener; - } - - @Override - public void configure(WebSocketServletFactory factory) { - factory.setCreator(new IdscpWebSocketCreator(this.config, this.socketListener)); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/SocketListener.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/SocketListener.java deleted file mode 100644 index c6400e513..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/server/SocketListener.java +++ /dev/null @@ -1,37 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.server; - -import org.eclipse.jetty.websocket.api.Session; - -public interface SocketListener { - - /** - * This method is called on every incoming payload message. - * - *

Implementations of this interface should handle payloads here. - * - * @param session - * @param message - */ - void onMessage(Session session, byte[] message); - - void notifyClosed(IdscpServerSocket idscpServerSocket); -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/ClientProtocolMachine.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/ClientProtocolMachine.java deleted file mode 100644 index f3933fc5a..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/ClientProtocolMachine.java +++ /dev/null @@ -1,197 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol; - -import com.google.protobuf.MessageLite; -import de.fhg.aisec.ids.api.tokenm.DatException; -import de.fhg.aisec.ids.comm.DatVerifier; -import de.fhg.aisec.ids.comm.client.ClientConfiguration; -import de.fhg.aisec.ids.comm.ws.protocol.error.ErrorHandler; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.FSM; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Transition; -import de.fhg.aisec.ids.comm.ws.protocol.metadata.MetadataConsumerHandler; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationClientHandler; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationHandler; -import de.fhg.aisec.ids.messages.Idscp; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import java.net.URI; -import java.util.Arrays; -import org.asynchttpclient.ws.WebSocket; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class generates the Finite State Machine (FSM) for the IDS protocol. - * - * @author Julian Schütte - * @author Georg Räß - * @author Gerd Brost - * @author Michael Lux - */ -public class ClientProtocolMachine extends FSM { - private static final Logger LOG = LoggerFactory.getLogger(ClientProtocolMachine.class); - - private WebSocket clientSocket; - - /** - * Constructor of a finite state machine (FSM) implementing the IDSP protocol. - * - *

The FSM will be in its initial state and ready to accept messages via FSM.feedEvent() - * . It will send responses over the session according to its FSM definition. - */ - public ClientProtocolMachine(WebSocket ws, ClientConfiguration clientConfiguration, - DatVerifier datVerifier) { - this.clientSocket = ws; - - // set trusted third party URL - URI ttp = clientConfiguration.getTrustedThirdPartyURI(); - // all handler - RemoteAttestationClientHandler ratConsumerHandler = - new RemoteAttestationClientHandler( - clientConfiguration, ttp, RemoteAttestationHandler.CONTROL_SOCKET); - ErrorHandler errorHandler = new ErrorHandler(); - MetadataConsumerHandler metaHandler = - new MetadataConsumerHandler( - clientConfiguration.getRDFDescription(), - clientConfiguration.getDynamicAttributeToken()); - - // Standard protocol states - this.addState(ProtocolState.IDSCP_START); - this.addState(ProtocolState.IDSCP_ERROR); - this.addState(ProtocolState.IDSCP_END); - - // Remote attestation states - this.addState(ProtocolState.IDSCP_RAT_AWAIT_REQUEST); - this.addState(ProtocolState.IDSCP_RAT_AWAIT_RESPONSE); - this.addState(ProtocolState.IDSCP_RAT_AWAIT_RESULT); - this.addState(ProtocolState.IDSCP_RAT_AWAIT_LEAVE); - - // Meta data exchange states - this.addState(ProtocolState.IDSCP_META_REQUEST); - this.addState(ProtocolState.IDSCP_META_RESPONSE); - - // Remote Attestation Protocol - this.addTransition( - new Transition( - ConnectorMessage.Type.RAT_START, - ProtocolState.IDSCP_START, - ProtocolState.IDSCP_RAT_AWAIT_REQUEST, - e -> replyProto(ratConsumerHandler.enterRatRequest(e)))); - this.addTransition( - new Transition( - ConnectorMessage.Type.RAT_REQUEST, - ProtocolState.IDSCP_RAT_AWAIT_REQUEST, - ProtocolState.IDSCP_RAT_AWAIT_RESPONSE, - e -> replyProto(ratConsumerHandler.sendTPM2Ddata(e)))); - this.addTransition( - new Transition( - ConnectorMessage.Type.RAT_RESPONSE, - ProtocolState.IDSCP_RAT_AWAIT_RESPONSE, - ProtocolState.IDSCP_RAT_AWAIT_RESULT, - e -> replyProto(ratConsumerHandler.sendResult(e)))); - this.addTransition( - new Transition( - ConnectorMessage.Type.RAT_RESULT, - ProtocolState.IDSCP_RAT_AWAIT_RESULT, - ProtocolState.IDSCP_RAT_AWAIT_LEAVE, - e -> { - MessageLite message = ratConsumerHandler.leaveRatRequest(e); - this.handleRatResult( - ratConsumerHandler.handleAttestationResult( - e.getMessage().getAttestationResult())); - return replyProto(message); - })); - - // Metadata Exchange Protocol - this.addTransition( - new Transition( - ConnectorMessage.Type.RAT_LEAVE, - ProtocolState.IDSCP_RAT_AWAIT_LEAVE, - ProtocolState.IDSCP_META_REQUEST, - e -> replyProto(metaHandler.request(e)))); - this.addTransition( - new Transition( - ConnectorMessage.Type.META_RESPONSE, - ProtocolState.IDSCP_META_REQUEST, - ProtocolState.IDSCP_END, - e -> { - var mex = e.getMessage().getMetadataExchange(); - this.setMetaData(mex.getRdfdescription()); - this.setDynamicAttributeToken(mex.getDynamicAttributeToken()); - try { - datVerifier.verify(getDynamicAttributeToken()); - LOG.info("DAT successfully verified."); - return true; - } catch (DatException de) { - LOG.warn("Error during DAT verification", de); - return false; - } - })); - - // Error transitions - // in case of error, either fast forward to meta exchange (if in rat) or go to END - ProtocolState[] errorStartStates = - new ProtocolState[] { - ProtocolState.IDSCP_START, - ProtocolState.IDSCP_RAT_AWAIT_REQUEST, - ProtocolState.IDSCP_RAT_AWAIT_RESPONSE, - ProtocolState.IDSCP_RAT_AWAIT_RESULT, - ProtocolState.IDSCP_RAT_AWAIT_LEAVE, - ProtocolState.IDSCP_META_REQUEST, - ProtocolState.IDSCP_META_RESPONSE - }; - Arrays.stream(errorStartStates) - .forEach(state -> this.addTransition(makeConsumerErrorTransition(state, errorHandler))); - - // Add listener to log state transitions - this.addSuccessChangeListener( - (f, e) -> - LOG.debug(String.format("Consumer State change: %s -> %s", e.getKey(), f.getState()))); - - // String graph = this.toDot(); - // System.out.println(graph); - - /* Run the FSM */ - this.setInitialState(ProtocolState.IDSCP_START); - } - - protected Transition makeConsumerErrorTransition(ProtocolState state, ErrorHandler errorHandler) { - return new Transition( - ConnectorMessage.Type.ERROR, - state, - ProtocolState.IDSCP_END, - e -> errorHandler.handleError(e, state, true)); - } - - private boolean replyProto(MessageLite message) { - return reply(message.toByteArray()); - } - - /** - * Sends a response over the websocket session. - * - * @param text Bytes to send to client - * @return true if successful, false if not. - */ - private boolean reply(byte[] text) { - this.clientSocket.sendBinaryFrame(text); - return true; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/IDSCPException.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/IDSCPException.java deleted file mode 100644 index 36dcfce06..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/IDSCPException.java +++ /dev/null @@ -1,30 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol; - -public class IDSCPException extends RuntimeException { - public IDSCPException(String message) { - super(message); - } - - public IDSCPException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/ProtocolState.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/ProtocolState.java deleted file mode 100644 index a1d418560..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/ProtocolState.java +++ /dev/null @@ -1,78 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Definition of FSM states for IDS protocol. - * - * @author Julian Schuette (julian.schuette@aisec.fraunhofer.de) - * @author Georg Raess (georg.raess@aisec.fraunhofer.de) - */ -public final class ProtocolState { - private String id; - private String description; - public final int ord; - private static AtomicInteger upperBound = new AtomicInteger(0); - - /* -------------- States start here ------------ */ - public static final ProtocolState IDSCP_START = - new ProtocolState("IDSCP:START", "Idscp: start of protocol."); - public static final ProtocolState IDSCP_ERROR = - new ProtocolState("IDSCP:ERROR", "Idscp: error in protocol."); - public static final ProtocolState IDSCP_END = - new ProtocolState("IDSCP:END", "Idscp: end of protocol."); - public static final ProtocolState IDSCP_RAT_AWAIT_RESPONSE = - new ProtocolState("IDSCP:RAT:AWAIT_RESPONSE", "Idscp/RemoteAttestation: awaiting response."); - public static final ProtocolState IDSCP_RAT_AWAIT_REQUEST = - new ProtocolState("IDSCP:RAT:AWAIT_REQUEST", "Idscp/RemoteAttestation: awaiting request."); - public static final ProtocolState IDSCP_RAT_AWAIT_RESULT = - new ProtocolState("IDSCP:RAT:AWAIT_RESULT", "Idscp/RemoteAttestation: awaiting result."); - public static final ProtocolState IDSCP_RAT_AWAIT_LEAVE = - new ProtocolState("IDSCP:RAT:AWAIT_LEAVE", "Idscp/RemoteAttestation: awaiting to leave."); - public static final ProtocolState IDSCP_META_REQUEST = - new ProtocolState("IDSCP:META:REQUEST", "Idscp/Metadataexchange: request."); - public static final ProtocolState IDSCP_META_RESPONSE = - new ProtocolState("IDSCP:META:RESPONSE", "Idscp/Metadataexchange: response."); - /* -------------- States end here ------------ */ - - private ProtocolState(String id, String description) { - this.id = id; - this.description = description; - this.ord = upperBound.getAndIncrement(); - } - - public String id() { - return this.id; - } - - public String description() { - return this.description; - } - - public static int size() { - return upperBound.get(); - } - - public String toString() { - return this.description() + " (id: " + this.id() + ")"; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/ServerProtocolMachine.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/ServerProtocolMachine.java deleted file mode 100644 index b10a2cd6c..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/ServerProtocolMachine.java +++ /dev/null @@ -1,219 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol; - -import com.google.protobuf.MessageLite; -import de.fhg.aisec.ids.api.tokenm.DatException; -import de.fhg.aisec.ids.comm.DatVerifier; -import de.fhg.aisec.ids.comm.server.ServerConfiguration; -import de.fhg.aisec.ids.comm.ws.protocol.error.ErrorHandler; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.FSM; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Transition; -import de.fhg.aisec.ids.comm.ws.protocol.metadata.MetadataProviderHandler; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationHandler; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationServerHandler; -import de.fhg.aisec.ids.messages.Idscp.AttestationResult; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import de.fhg.aisec.ids.messages.Idscp.Error; -import java.io.IOException; -import java.net.URI; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.function.Function; - -import org.eclipse.jetty.websocket.api.Session; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class generates the Finite State Machine (FSM) for the IDS protocol. - * - * @author Julian Schütte - * @author Georg Räß - * @author Gerd Brost - * @author Michael Lux - */ -public class ServerProtocolMachine extends FSM { - private static final Logger LOG = LoggerFactory.getLogger(ServerProtocolMachine.class); - - private Session serverSession; - private AttestationResult attestationResult; - - public ServerProtocolMachine(Session sess, ServerConfiguration serverConfiguration, - DatVerifier datVerifier) { - this.serverSession = sess; - - // set trusted third party URL - URI ttp = serverConfiguration.getTrustedThirdPartyURI(); - - // all handler - RemoteAttestationServerHandler ratProviderHandler = - new RemoteAttestationServerHandler( - serverConfiguration, ttp, RemoteAttestationHandler.CONTROL_SOCKET); - ErrorHandler errorHandler = new ErrorHandler(); - MetadataProviderHandler metaHandler = - new MetadataProviderHandler( - serverConfiguration.getRDFDescription(), - serverConfiguration.getDynamicAttributeToken()); - - // Standard protocol states - this.addState(ProtocolState.IDSCP_START); - this.addState(ProtocolState.IDSCP_ERROR); - this.addState(ProtocolState.IDSCP_END); - - // Remote Attestation states - this.addState(ProtocolState.IDSCP_RAT_AWAIT_REQUEST); - this.addState(ProtocolState.IDSCP_RAT_AWAIT_RESPONSE); - this.addState(ProtocolState.IDSCP_RAT_AWAIT_RESULT); - this.addState(ProtocolState.IDSCP_RAT_AWAIT_LEAVE); - - // Metadata exchange states - this.addState(ProtocolState.IDSCP_META_REQUEST); - this.addState(ProtocolState.IDSCP_META_RESPONSE); - - // Remote Attestation Protocol - this.addTransition( - new Transition( - ConnectorMessage.Type.RAT_REQUEST, - ProtocolState.IDSCP_START, - ProtocolState.IDSCP_RAT_AWAIT_RESPONSE, - e -> replyProto(ratProviderHandler.enterRatRequest(e)))); - this.addTransition( - new Transition( - ConnectorMessage.Type.RAT_RESPONSE, - ProtocolState.IDSCP_RAT_AWAIT_RESPONSE, - ProtocolState.IDSCP_RAT_AWAIT_RESULT, - e -> replyProto(ratProviderHandler.sendTPM2Ddata(e)))); - this.addTransition( - new Transition( - ConnectorMessage.Type.RAT_RESULT, - ProtocolState.IDSCP_RAT_AWAIT_RESULT, - ProtocolState.IDSCP_RAT_AWAIT_LEAVE, - e -> { - attestationResult = e.getMessage().getAttestationResult(); - return replyProto(ratProviderHandler.sendResult(e)); - })); - this.addTransition( - new Transition( - ConnectorMessage.Type.RAT_LEAVE, - ProtocolState.IDSCP_RAT_AWAIT_LEAVE, - ProtocolState.IDSCP_META_REQUEST, - e -> { - MessageLite message = ratProviderHandler.leaveRatRequest(e); - this.handleRatResult(ratProviderHandler.handleAttestationResult(attestationResult)); - return replyProto(message); - })); - - // Metadata Exchange Protocol - this.addTransition( - new Transition( - ConnectorMessage.Type.META_REQUEST, - ProtocolState.IDSCP_META_REQUEST, - ProtocolState.IDSCP_END, - e -> { - var mex = e.getMessage().getMetadataExchange(); - this.setMetaData(mex.getRdfdescription()); - this.setDynamicAttributeToken(mex.getDynamicAttributeToken()); - try { - datVerifier.verify(getDynamicAttributeToken()); - LOG.info("DAT successfully verified."); - return replyProto(metaHandler.response(e)); - } catch (Exception de) { - LOG.warn("Error during DAT verification", de); - replyProto(ConnectorMessage.newBuilder() - .setId(-1) - .setType(ConnectorMessage.Type.ERROR) - .setError(Error.newBuilder() - .setErrorCode("") - .setErrorMessage("DAT verification failed: " + de.getMessage()) - .build()) - .build()); - return false; - } - })); - - // Error transitions - // in case of error, either fast forward to meta exchange (if in rat) or go to END - ProtocolState[] errorStartStates = - new ProtocolState[] { - ProtocolState.IDSCP_START, - ProtocolState.IDSCP_RAT_AWAIT_REQUEST, - ProtocolState.IDSCP_RAT_AWAIT_RESPONSE, - ProtocolState.IDSCP_RAT_AWAIT_RESULT, - ProtocolState.IDSCP_RAT_AWAIT_LEAVE, - ProtocolState.IDSCP_META_REQUEST, - ProtocolState.IDSCP_META_RESPONSE - }; - Arrays.stream(errorStartStates) - .forEach(state -> this.addTransition(makeProviderErrorTransition(state, errorHandler))); - - /* Add listener to log state transitions */ - this.addSuccessChangeListener( - (f, e) -> - LOG.debug(String.format("Provider State change: %s -> %s", e.getKey(), f.getState()))); - - // String graph = this.toDot(); - // System.out.println(graph); - - /* Run the FSM */ - this.setInitialState(ProtocolState.IDSCP_START); - } - - private Transition makeProviderErrorTransition(ProtocolState state, ErrorHandler errorHandler) { - return new Transition( - ConnectorMessage.Type.ERROR, - state, - ProtocolState.IDSCP_END, - e -> { - errorHandler.handleError(e, state, false); - LOG.debug("Client sending abort"); - MessageLite abortMessage = - ConnectorMessage.newBuilder() - .setId(0) - .setType(ConnectorMessage.Type.ERROR) - .setError(Error.newBuilder().setErrorCode("").setErrorMessage("Abort").build()) - .build(); - return reply(abortMessage.toByteArray()); - }); - } - - private boolean replyProto(MessageLite message) { - return reply(message.toByteArray()); - } - - /** - * Sends a response over the websocket session. - * - * @param text Bytes to send to client - * @return true if successful, false if not. - */ - private boolean reply(byte[] text) { - try { - ByteBuffer bb = ByteBuffer.wrap(text); - LOG.trace("Sending out ByteBuffer with {} bytes", bb.array().length); - serverSession.getRemote().sendBytes(bb); - serverSession.getRemote().flush(); - return true; - } catch (IOException e) { - LOG.error(e.getMessage(), e); - return false; - } - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/error/ErrorHandler.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/error/ErrorHandler.java deleted file mode 100644 index a7e3ecea7..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/error/ErrorHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.error; - -import de.fhg.aisec.ids.comm.ws.protocol.ProtocolState; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@SuppressWarnings("unused") -public class ErrorHandler { - private static final Logger LOG = LoggerFactory.getLogger(ErrorHandler.class); - - public boolean handleError(Event e, ProtocolState state, boolean isConsumer) { - String entity = isConsumer ? "Consumer" : "Provider"; - - LOG.debug( - "**************************************************************************************************"); - LOG.debug("* error handler during rat protocol execution "); - LOG.debug("* -> state: " + state.description()); - LOG.debug("* -> side: " + entity + ""); - LOG.debug("* -> error: " + e.getMessage().getError().getErrorMessage()); - LOG.debug( - "**************************************************************************************************"); - - return true; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/ChangeListener.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/ChangeListener.java deleted file mode 100644 index ba98eecc5..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/ChangeListener.java +++ /dev/null @@ -1,30 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.fsm; - -/** - * Functional interface for listeners which are notified whenever the state of a FSM changes. - * - * @author Julian Schuette (julian.schuette@aisec.fraunhofer.de) - */ -public interface ChangeListener { - - void stateChanged(FSM fsm, Event event); -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/Event.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/Event.java deleted file mode 100644 index d711b140e..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/Event.java +++ /dev/null @@ -1,64 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.fsm; - -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; - -/** - * An FSM event which may trigger a transition. - * - * @author Julian Schuette (julian.schuette@aisec.fraunhofer.de) - */ -public class Event { - private Object key; - private String payload; - private ConnectorMessage msg; - - public Event(Object key, String payload, ConnectorMessage msg) { - super(); - this.setKey(key); - this.setPayload(payload); - this.setMessage(msg); - } - - public Object getKey() { - return key; - } - - public void setKey(Object key) { - this.key = key; - } - - public ConnectorMessage getMessage() { - return this.msg; - } - - public void setMessage(ConnectorMessage evt) { - this.msg = evt; - } - - public String getPayload() { - return this.payload; - } - - public void setPayload(String payload) { - this.payload = payload; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/FSM.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/FSM.java deleted file mode 100644 index 0421adba1..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/FSM.java +++ /dev/null @@ -1,213 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.fsm; - -import de.fhg.aisec.ids.api.conm.RatResult; -import de.fhg.aisec.ids.comm.ws.protocol.ProtocolState; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; - -/** - * Implementation of a finite state machine (FSM). - * - * @author Julian Schuette (julian.schuette@aisec.fraunhofer.de) - */ -public class FSM { - - protected String currentState = null; - protected Map states; - protected HashSet successChangeListeners; - protected HashSet failChangeListeners; - private String initialState = null; - private RatResult ratResult; - private String metaData; - private String dynamicAttributeToken; - - public FSM() { - this.states = new HashMap<>(); - this.successChangeListeners = new HashSet<>(); - this.failChangeListeners = new HashSet<>(); - } - - public String getState() { - return currentState; - } - - public void addState(ProtocolState state) { - addState(state.id(), null, null, null); - } - - /** - * Defines an additional state. A state is identified by a name and has three blocks of code - * assigned to it: - * - *

1) entryCode is executed when the state is entered from another state (after the - * transition's code has been executed) - * - *

2) exitCode is executed when the state is left for another state (before the transition's - * code is executed) - * - *

3) alwaysRunCode is always executed when the FSM enters this state (even if it has been in - * that state before) - * - *

All three Runnables may be null. Their result has no impact on the FSM's state, Exceptions - * thrown are ignored. - * - * @param state - * @param entryCode - * @param exitCode - * @param alwaysRunCode - */ - public void addState( - String state, Runnable entryCode, Runnable exitCode, Runnable alwaysRunCode) { - if (states.size() == 0) { - this.initialState = state; - this.currentState = state; - } - if (!states.containsKey(state)) { - states.put(state, new State(entryCode, exitCode, alwaysRunCode)); - } else { - throw new NoSuchElementException("Missing state: " + state); - } - } - - /** - * Defines initial state of this FSM. If no initial state is defined explicitly, the first added - * state is the initial state. - * - * @param state The initial state of this FSM - */ - public void setInitialState(ProtocolState state) { - if (!this.states.containsKey(state.id())) { - throw new NoSuchElementException("Missing state: " + state.id()); - } - this.initialState = state.id(); - } - - /** Resets FSM to it initial state */ - public void reset() { - this.currentState = this.initialState; - } - - private void setState(String state) { - boolean runExtraCode = !state.equals(currentState); - if (runExtraCode && currentState != null) { - states.get(currentState).runExitCode(); - } - currentState = state; - states.get(currentState).runAlwaysCode(); - if (runExtraCode) { - states.get(currentState).runEntryCode(); - } - - // If event-less transition is defined for current node, trigger it immediately - if (states.get(currentState).transitions.containsKey(null)) { - feedEvent(null); - } - } - - /** - * Add a new transition to this FSM. - * - * @param trans The transition to be added to this FSM - */ - public void addTransition(Transition trans) { - State st = states.get(trans.startState); - if (st == null) { - throw new NoSuchElementException("Missing start state: " + trans.startState); - } - if (!states.containsKey(trans.endState)) { - throw new NoSuchElementException("Missing end state: " + trans.endState); - } - st.addTransition(trans); - } - - public void addSuccessChangeListener(ChangeListener cl) { - successChangeListeners.add(cl); - } - - public void addFailChangeListener(ChangeListener cl) { - failChangeListeners.add(cl); - } - - public void feedEvent(Event event) { - Object evtKey = event.getKey(); - State state = states.get(currentState); - Transition trans = state.transitions.get(evtKey); - if (trans != null) { - if (trans.doBeforeTransition(event)) { - setState(trans.endState); - successChangeListeners.forEach(l -> l.stateChanged(this, event)); - } else { - failChangeListeners.forEach(l -> l.stateChanged(this, event)); - } - } - } - - public String toDot() { - StringBuilder sb = new StringBuilder(); - sb.append("digraph finite_state_machine {\n"); - sb.append(" rankdir=LR;\n"); - sb.append(" node [shape = ellipse];\n"); - for (Entry from : states.entrySet()) { - for (Object t : from.getValue().transitions.keySet()) { - String to = from.getValue().transitions.get(t).endState; - Object eventKey = from.getValue().transitions.get(t).event; - sb.append( - " " - + from.getKey().replace(':', '_') - + " -> " - + to.replace(':', '_') - + " [ label=\"" - + eventKey - + "\" ];\n"); - } - } - sb.append(" }"); - return sb.toString(); - } - - public void handleRatResult(RatResult attestationResult) { - this.ratResult = attestationResult; - } - - public RatResult getRatResult() { - return ratResult; - } - - public void setMetaData(String metaData) { - this.metaData = metaData; - } - - public String getMetaData() { - return this.metaData; - } - - public void setDynamicAttributeToken(String dynamicAttributeToken) { - this.dynamicAttributeToken = dynamicAttributeToken; - } - - public String getDynamicAttributeToken() { - return this.dynamicAttributeToken; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/State.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/State.java deleted file mode 100644 index a79fcc964..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/State.java +++ /dev/null @@ -1,65 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.fsm; - -import java.util.HashMap; -import java.util.Map; - -/** Represents a state with some number of associated transitions. */ -class State { - // map from event key to transition - Map transitions = new HashMap<>(); - Runnable entryCode; - Runnable exitCode; - Runnable alwaysRunCode; - - State(Runnable entryCode, Runnable exitCode, Runnable alwaysRunCode) { - this.entryCode = entryCode; - this.exitCode = exitCode; - this.alwaysRunCode = alwaysRunCode; - } - - public void addTransition(Transition trans) { - // Fail fast for duplicate transitions - if (transitions.containsKey(trans.event)) { - throw new IllegalArgumentException( - "Transition for event " + trans.event + " already exists."); - } - transitions.put(trans.event, trans); - } - - public void runEntryCode() { - if (entryCode != null) { - entryCode.run(); - } - } - - public void runExitCode() { - if (exitCode != null) { - exitCode.run(); - } - } - - public void runAlwaysCode() { - if (alwaysRunCode != null) { - alwaysRunCode.run(); - } - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/Transition.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/Transition.java deleted file mode 100644 index 5d5ecdda6..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/fsm/Transition.java +++ /dev/null @@ -1,100 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.fsm; - -import de.fhg.aisec.ids.comm.ws.protocol.ProtocolState; -import java.util.function.Function; -import org.slf4j.LoggerFactory; - -/** - * A Transition transfers the FSM from a start state to an end state and is triggered by an event. - * - *

Associated with a transition is code that is executed when the transition is taken. - */ -public class Transition { - final Object event; - final String startState; - final String endState; - final Function runBeforeTransition; - - /** - * Creates a new transition. - * - * @param eventName the event triggering this transition. - * @param startState the start state of this transition. - * @param endState the end state of this transition. - * @param runBeforeTransition code executed when the transition is triggered. If the callable - * returns true, the transition takes place, if the callable returns false, the transition - * will not take place and the FSM remains in startState. - */ - public Transition( - String eventName, - String startState, - String endState, - Function runBeforeTransition) { - this.event = eventName; - this.startState = startState; - this.endState = endState; - this.runBeforeTransition = runBeforeTransition; - } - - public Transition( - Object evtKey, - String startState, - String endState, - Function runBeforeTransition) { - this.event = evtKey; - this.startState = startState; - this.endState = endState; - this.runBeforeTransition = runBeforeTransition; - } - - public Transition( - Object evtKey, - ProtocolState startState, - ProtocolState endState, - Function runBeforeTransition) { - this.event = evtKey; - this.startState = startState.id(); - this.endState = endState.id(); - this.runBeforeTransition = runBeforeTransition; - } - - /** - * Executes code associated with this transition. - * - *

This method returns the result of the executed Callable (true or false) or false in case of - * any Exceptions. No exceptions will be thrown from this method. - * - * @return Whether - */ - protected boolean doBeforeTransition(Event event) { - if (runBeforeTransition != null) { - try { - runBeforeTransition.apply(event); - } catch (Throwable t) { - LoggerFactory.getLogger(this.getClass().getName()) - .warn("Error in before-transition-procedure", t); - return false; - } - } - return true; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/metadata/MetadataConsumerHandler.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/metadata/MetadataConsumerHandler.java deleted file mode 100644 index 907080383..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/metadata/MetadataConsumerHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.metadata; - -import com.google.protobuf.MessageLite; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import de.fhg.aisec.ids.messages.Idscp.MedadataExchange; - -public class MetadataConsumerHandler extends MetadataHandler { - - public MetadataConsumerHandler(String rdfSelfDescription, String dynamicAttributeToken) { - super(rdfSelfDescription, dynamicAttributeToken); - } - - public MessageLite request(Event e) { - this.sessionID = e.getMessage().getId(); - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.META_REQUEST) - .setMetadataExchange( - MedadataExchange.newBuilder() - .setRdfdescription(getMetaData()) - .setDynamicAttributeToken(getDynamicAttributeToken()) - .build()) - .build(); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/metadata/MetadataHandler.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/metadata/MetadataHandler.java deleted file mode 100644 index 8fa558be8..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/metadata/MetadataHandler.java +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.metadata; - -import com.google.protobuf.MessageLite; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import de.fhg.aisec.ids.messages.Idscp.Error; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MetadataHandler { - protected static Logger LOG = LoggerFactory.getLogger(MetadataHandler.class); - protected static String lastError = ""; - protected long sessionID = -1; - protected String rdfSelfDescription = "THIS IS SOME META DATA"; - protected String dynamicAttributeToken = "INVALID_TOKEN"; - - public MetadataHandler() {} - - public MetadataHandler(String rdfSelfDescription, String dynamicAttributeToken) { - this.rdfSelfDescription = rdfSelfDescription; - this.dynamicAttributeToken = dynamicAttributeToken; - } - - public String getMetaData() { - - return this.rdfSelfDescription; - } - - public String getDynamicAttributeToken() { - return this.dynamicAttributeToken; - } - - public static MessageLite sendError(String lastError) { - return ConnectorMessage.newBuilder() - .setId(0) - .setType(ConnectorMessage.Type.ERROR) - .setError(Error.newBuilder().setErrorCode("").setErrorMessage(lastError).build()) - .build(); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/metadata/MetadataProviderHandler.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/metadata/MetadataProviderHandler.java deleted file mode 100644 index d1882502e..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/metadata/MetadataProviderHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.metadata; - -import com.google.protobuf.MessageLite; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import de.fhg.aisec.ids.messages.Idscp.MedadataExchange; - -public class MetadataProviderHandler extends MetadataHandler { - public MetadataProviderHandler(String rdfSelfDescription, String dynamicAttributeToken) { - super(rdfSelfDescription, dynamicAttributeToken); - } - - public MessageLite response(Event e) { - this.sessionID = e.getMessage().getId(); - - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.META_RESPONSE) - .setMetadataExchange( - MedadataExchange.newBuilder() - .setRdfdescription(getMetaData()) - .setDynamicAttributeToken(getDynamicAttributeToken()) - .build()) - .build(); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/NonceGenerator.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/NonceGenerator.java deleted file mode 100644 index 99fa9a2ca..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/NonceGenerator.java +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.rat; - -import java.security.SecureRandom; - -public final class NonceGenerator { - private static final SecureRandom sr = new SecureRandom(); - - private NonceGenerator() {} - - /** - * Generate a crypto-secure random hex String of length numChars - * - * @param numBytes Desired String length - * @return The generated crypto-secure random hex String - */ - public static byte[] generate(int numBytes) { - byte[] randBytes = new byte[numBytes]; - sr.nextBytes(randBytes); - return randBytes; - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/RemoteAttestationClientHandler.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/RemoteAttestationClientHandler.java deleted file mode 100644 index 1b1615dd8..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/RemoteAttestationClientHandler.java +++ /dev/null @@ -1,191 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.rat; - -import com.google.protobuf.ByteString; -import com.google.protobuf.MessageLite; -import de.fhg.aisec.ids.comm.CertificatePair; -import de.fhg.aisec.ids.comm.IdscpConfiguration; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import de.fhg.aisec.ids.messages.AttestationProtos.Pcr; -import de.fhg.aisec.ids.messages.AttestationProtos.RemoteToTpm2d; -import de.fhg.aisec.ids.messages.AttestationProtos.RemoteToTpm2d.Code; -import de.fhg.aisec.ids.messages.AttestationProtos.Tpm2dToRemote; -import de.fhg.aisec.ids.messages.Idscp.*; -import java.io.IOException; -import java.net.URI; -import java.util.Collections; -import java.util.List; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class RemoteAttestationClientHandler extends RemoteAttestationHandler { - private static final Logger LOG = LoggerFactory.getLogger(RemoteAttestationClientHandler.class); - private byte[] myNonce; - private byte[] yourNonce; - private IdsAttestationType aType; - private long sessionID = 0; // used to count messages between ids connectors during attestation - private final URI ttpUri; - private final int attestationMask; - private final CertificatePair certificatePair; - - public RemoteAttestationClientHandler( - @NonNull IdscpConfiguration clientConfiguration, - @Nullable URI ttpUri, - @Nullable String socket) { - // set ttp uri - this.ttpUri = ttpUri; - // set current attestation type and mask (see attestation.proto) - this.aType = clientConfiguration.getAttestationType(); - this.attestationMask = clientConfiguration.getAttestationMask(); - this.certificatePair = clientConfiguration.getCertificatePair(); - } - - public MessageLite enterRatRequest(@NonNull Event e) { - // generate a new software nonce on the client and send it to server - this.myNonce = NonceGenerator.generate(20); - // get starting session id - this.sessionID = e.getMessage().getId(); - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.RAT_REQUEST) - .setAttestationRequest( - AttestationRequest.newBuilder() - .setAtype(this.aType) - .setNonce(ByteString.copyFrom(this.myNonce)) - .build()) - .build(); - } - - public MessageLite sendTPM2Ddata(@NonNull Event e) { - // get nonce from server msg - this.yourNonce = e.getMessage().getAttestationRequest().getNonce().toByteArray(); - final byte[] hash = calculateHash(this.yourNonce, certificatePair.getRemoteCertificate()); - - if (++this.sessionID != e.getMessage().getId()) { - return RemoteAttestationHandler.sendError( - ++this.sessionID, "Invalid session ID " + e.getMessage().getId()); - } - - String halg = ""; - ByteString quoted = ByteString.EMPTY; - ByteString signature = ByteString.EMPTY; - List pcrValues = Collections.emptyList(); - ByteString certificate = ByteString.EMPTY; - if (tpm2dSocket != null) { - try { - RemoteToTpm2d.Builder msgBuilder = - RemoteToTpm2d.newBuilder() - .setAtype(this.aType) - .setQualifyingData(ByteString.copyFrom(hash)) - .setCode(Code.ATTESTATION_REQ) - .setPcrs(this.attestationMask); - if (this.aType.equals(IdsAttestationType.ADVANCED)) { - // send msg to local unix socket with bitmask set - // construct protobuf message to send to local tpm2d via unix socket - msgBuilder.setPcrs(this.attestationMask); - } - Tpm2dToRemote response = tpm2dSocket.requestAttestation(msgBuilder.build()); - halg = response.getHalg().name(); - quoted = response.getQuoted(); - signature = response.getSignature(); - pcrValues = response.getPcrValuesList(); - certificate = response.getCertificate(); - } catch (IOException ex) { - lastError = "IOException during communication with tpm2d: " + ex.getMessage(); - LOG.error(lastError, ex); - } - } else { - LOG.warn("Tpm2dSocket is not available. No TPM present?"); - } - // now return values from answer to provider - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.RAT_RESPONSE) - .setAttestationResponse( - AttestationResponse.newBuilder() - .setAtype(this.aType) - .setHalg(halg) - .setQuoted(quoted) - .setSignature(signature) - .addAllPcrValues(pcrValues) - .setCertificate(certificate) - .build()) - .build(); - } - - public MessageLite sendResult(@NonNull Event e) { - final byte[] hash = calculateHash(this.myNonce, certificatePair.getLocalCertificate()); - AttestationResponse response = e.getMessage().getAttestationResponse(); - assert response != null; - - // Abort on wrong session ID - if (++this.sessionID != e.getMessage().getId()) { - lastError = - "error: sessionID not correct ! (is " - + e.getMessage().getId() - + " but should have been " - + (this.sessionID + 1) - + ")"; - LOG.debug(lastError); - return RemoteAttestationHandler.sendError( - ++this.sessionID, RemoteAttestationHandler.lastError); - } - - if (this.checkSignature(response, hash) && checkRepository(this.aType, response, ttpUri)) { - this.mySuccess = true; - } else { - LOG.warn( - "Could not verify signature or could not validate PCR values via trusted third party. " - + "Remote attestation failed."); - } - - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.RAT_RESULT) - .setAttestationResult( - AttestationResult.newBuilder().setAtype(this.aType).setResult(this.mySuccess).build()) - .build(); - } - - public MessageLite leaveRatRequest(@NonNull Event e) { - // Abort on wrong session ID - if (++this.sessionID != e.getMessage().getId()) { - lastError = - "error: sessionID not correct ! (is " - + e.getMessage().getId() - + " but should have been " - + (this.sessionID + 1) - + ")"; - LOG.debug(lastError); - return RemoteAttestationHandler.sendError( - ++this.sessionID, RemoteAttestationHandler.lastError); - } - - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.RAT_LEAVE) - .setAttestationLeave(AttestationLeave.newBuilder().setAtype(this.aType).build()) - .build(); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/RemoteAttestationHandler.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/RemoteAttestationHandler.java deleted file mode 100644 index 80f3527f5..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/RemoteAttestationHandler.java +++ /dev/null @@ -1,302 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.rat; - -import com.google.protobuf.MessageLite; -import de.fhg.aisec.ids.api.conm.RatResult; -import de.fhg.aisec.ids.comm.ByteArrayUtil; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import de.fhg.aisec.ids.messages.AttestationProtos.Pcr; -import de.fhg.aisec.ids.messages.Idscp.*; -import de.fhg.aisec.ids.messages.Idscp.Error; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.net.URI; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.Signature; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Base64; -import java.util.List; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import tss.tpm.*; - -public class RemoteAttestationHandler { - public static final String CONTROL_SOCKET = "/var/run/tpm2d/control.sock"; - protected static final Logger LOG = LoggerFactory.getLogger(RemoteAttestationClientHandler.class); - static String lastError = ""; - // used to count messages between ids connector and attestation repository - private static long privateID = new java.util.Random().nextLong(); - boolean mySuccess = false; - boolean yourSuccess = false; - Tpm2dSocket tpm2dSocket; - - RemoteAttestationHandler() { - // Tpm2dSocket used to communicate with local TPM2d - try { - String host = System.getenv("TPM_HOST") != null ? System.getenv("TPM_HOST") : "localhost"; - tpm2dSocket = new Tpm2dSocket(host); - } catch (IOException e) { - lastError = "Could not create Tpm2dSocket. No TPM present?"; - LOG.warn(lastError); - } - } - - public RatResult handleAttestationResult(@NonNull AttestationResult result) { - this.yourSuccess = result.getResult(); - - LOG.debug("your success: {} my success: {}", this.yourSuccess, this.mySuccess); - if (!this.mySuccess) { - return new RatResult(RatResult.Status.FAILED, "Could not verify"); - } - - if (!this.yourSuccess) { - return new RatResult(RatResult.Status.FAILED, "Remote party did not verify successfully"); - } - - return new RatResult(RatResult.Status.SUCCESS, null); - } - - static boolean checkRepository( - @Nullable IdsAttestationType aType, - @Nullable AttestationResponse response, - @Nullable URI ttpUri) { - if (aType == null || response == null || ttpUri == null) { - return false; - } - - List values = response.getPcrValuesList(); - try { - @SuppressWarnings("null") - ConnectorMessage msgRepo = - RemoteAttestationHandler.readRepositoryResponse( - ConnectorMessage.newBuilder() - .setId(privateID) - .setType(ConnectorMessage.Type.RAT_REPO_REQUEST) - .setAttestationRepositoryRequest( - AttestationRepositoryRequest.newBuilder() - .setAtype(aType) - .addAllPcrValues(values) - .build()) - .build(), - ttpUri.toURL()); - - LOG.debug("//Q///////////////////////////////////////////////////////////////////////////"); - LOG.debug(response.toString()); - LOG.debug("//A///////////////////////////////////////////////////////////////////////////"); - LOG.debug(msgRepo.toString()); - LOG.debug("/////////////////////////////////////////////////////////////////////////////"); - - // TODO : signature check of repo answer ... ! - return (msgRepo.getAttestationRepositoryResponse().getResult() - && (msgRepo.getId() == privateID + 1) - && (msgRepo.getType().equals(ConnectorMessage.Type.RAT_REPO_RESPONSE))); - - } catch (Exception ex) { - lastError = "Exception: " + ex.getMessage(); - LOG.error("Exception in checkRepository(): ", ex); - return false; - } - } - - /** - * Calculate SHA-1 hash of (nonce|certificate). - * - * @param nonce The plain, initial nonce - * @param certificate The certificate to hash-combine with the nonce - * @return The new nonce, updated with the given certificate using SHA-1 - */ - static byte[] calculateHash(byte[] nonce, @Nullable Certificate certificate) { - try { - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - digest.update(nonce); - if (certificate != null) { - digest.update(certificate.getEncoded()); - } else { - LOG.warn( - "No client certificate available. Cannot bind nonce to public key to prevent masquerading attack. TLS misconfiguration!"); - } - return digest.digest(); - } catch (Exception e1) { - LOG.error("Could not create hash of own nonce and local certificate", e1); - return nonce; - } - } - - boolean checkSignature(@NonNull AttestationResponse response, byte[] hash) { - byte[] byteSignature = response.getSignature().toByteArray(); - byte[] byteCert = response.getCertificate().toByteArray(); - byte[] byteQuoted = response.getQuoted().toByteArray(); - if (LOG.isDebugEnabled()) { - LOG.debug("signature: {}", ByteArrayUtil.toPrintableHexString(byteSignature)); - LOG.debug("cert: {}", ByteArrayUtil.toPrintableHexString(byteCert)); - LOG.debug("quoted: {}", ByteArrayUtil.toPrintableHexString(byteQuoted)); - } - - if (byteSignature.length == 0 || byteCert.length == 0 || byteQuoted.length == 0) { - LOG.warn("Some required part (signature, cert or quoted) is empty!"); - return false; - } - - try { - CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); - - // Load trust anchor certificate - final X509Certificate rootCertificate; - Path rootCertPath = FileSystems.getDefault().getPath("etc", "rootca-cert.pem"); - try (BufferedReader reader = - Files.newBufferedReader(rootCertPath, StandardCharsets.US_ASCII)) { - StringBuilder builder = new StringBuilder(); - for (String line = reader.readLine(); line != null; line = reader.readLine()) { - if (!line.startsWith("-")) { - builder.append(line.trim()); - } - } - byte[] rootCertBytes = Base64.getDecoder().decode(builder.toString()); - rootCertificate = - (X509Certificate) - certFactory.generateCertificate(new ByteArrayInputStream(rootCertBytes)); - } catch (Exception e) { - LOG.error("Error parsing root certificate", e); - return false; - } - - // Create X509Certificate instance from certBytes - final X509Certificate certificate = - (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(byteCert)); - // Verify the TPM certificate - try { - certificate.verify(rootCertificate.getPublicKey()); - } catch (Exception e) { - LOG.error("TPM certificate is invalid", e); - return false; - } - - // Construct a new TPMT_SIGNATURE instance from byteSignature bytes - final TPMT_SIGNATURE tpmtSignature; - try { - tpmtSignature = TPMT_SIGNATURE.fromTpm(byteSignature); - } catch (Exception ex) { - LOG.warn( - "Could not create a TPMT_SIGNATURE from bytes:\n" - + ByteArrayUtil.toPrintableHexString(byteSignature), - ex); - return false; - } - - // Construct a new TPMS_ATTEST instance from byteQuoted bytes - final TPMS_ATTEST tpmsAttest; - try { - tpmsAttest = TPMS_ATTEST.fromTpm(byteQuoted); - } catch (Exception ex) { - LOG.warn( - "Could not create a TPMS_ATTEST from bytes:\n" - + ByteArrayUtil.toPrintableHexString(byteQuoted), - ex); - return false; - } - - // check hash value (extra data) against expected hash - byte[] extraBytes = tpmsAttest.extraData; - if (!Arrays.equals(extraBytes, hash)) { - if (LOG.isWarnEnabled()) { - LOG.warn( - "The hash (extra data) in TPMS_ATTEST structure is invalid!" - + "\nextra data: {}\nhash: {}", - ByteArrayUtil.toPrintableHexString(extraBytes), - ByteArrayUtil.toPrintableHexString(hash)); - } - return false; - } - - // Check signature of attestation - final int tpmSigAlg = tpmtSignature.GetUnionSelector_signature(); - final int tpmSigHashAlg; - final byte[] tpmSig; - if (tpmSigAlg == TPM_ALG_ID.RSAPSS.toInt()) { - tpmSigHashAlg = ((TPMS_SIGNATURE_RSAPSS) tpmtSignature.signature).hash.toInt(); - tpmSig = ((TPMS_SIGNATURE_RSAPSS) tpmtSignature.signature).sig; - } else if (tpmSigAlg == TPM_ALG_ID.RSASSA.toInt()) { - tpmSigHashAlg = ((TPMS_SIGNATURE_RSASSA) tpmtSignature.signature).hash.toInt(); - tpmSig = ((TPMS_SIGNATURE_RSASSA) tpmtSignature.signature).sig; - } else { - throw new Exception( - "Unknown or unimplemented signature scheme: " + tpmtSignature.signature.getClass()); - } - if (tpmSigHashAlg != TPM_ALG_ID.SHA256.toInt()) { - throw new Exception("Only SHA256withRSA TPM signature hash algorithm is allowed!"); - } - Signature sig = Signature.getInstance("SHA256withRSA"); - sig.initVerify(certificate.getPublicKey()); - sig.update(byteQuoted); - boolean result = sig.verify(tpmSig); - if (!result && LOG.isWarnEnabled()) { - LOG.warn("Attestation signature invalid!"); - } - return result; - } catch (Exception ex) { - LOG.warn("Error during attestation validation", ex); - return false; - } - } - - static MessageLite sendError(long id, @Nullable String error) { - if (error == null) { - error = ""; - } - return ConnectorMessage.newBuilder() - .setId(id) - .setType(ConnectorMessage.Type.ERROR) - .setError(Error.newBuilder().setErrorCode("").setErrorMessage(error).build()) - .build(); - } - - private static ConnectorMessage readRepositoryResponse(@NonNull ConnectorMessage msg, URL adr) - throws IOException, GeneralSecurityException { - HttpsURLConnection urlc = (HttpsURLConnection) adr.openConnection(); - SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); - sslContext.init(null, null, null); - urlc.setSSLSocketFactory(sslContext.getSocketFactory()); - urlc.setUseCaches(false); - urlc.setDoInput(true); - urlc.setDoOutput(true); - urlc.setRequestMethod("POST"); - urlc.setRequestProperty("Accept", "application/x-protobuf"); - urlc.setRequestProperty("Content-Type", "application/x-protobuf"); - urlc.setRequestProperty("User-Agent", "IDS-Connector"); - urlc.setRequestProperty("Content-length", String.valueOf(msg.toByteArray().length)); - msg.writeTo(urlc.getOutputStream()); - return ConnectorMessage.newBuilder().mergeFrom(urlc.getInputStream()).build(); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/RemoteAttestationServerHandler.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/RemoteAttestationServerHandler.java deleted file mode 100644 index 56312fec2..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/RemoteAttestationServerHandler.java +++ /dev/null @@ -1,189 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.rat; - -import com.google.protobuf.ByteString; -import com.google.protobuf.MessageLite; -import de.fhg.aisec.ids.comm.CertificatePair; -import de.fhg.aisec.ids.comm.IdscpConfiguration; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import de.fhg.aisec.ids.messages.AttestationProtos.Pcr; -import de.fhg.aisec.ids.messages.AttestationProtos.RemoteToTpm2d; -import de.fhg.aisec.ids.messages.AttestationProtos.RemoteToTpm2d.Code; -import de.fhg.aisec.ids.messages.AttestationProtos.Tpm2dToRemote; -import de.fhg.aisec.ids.messages.Idscp.*; -import java.io.IOException; -import java.net.URI; -import java.util.Collections; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Implements the handling of individual protocol steps in the IDS remote attestation protocol. */ -public class RemoteAttestationServerHandler extends RemoteAttestationHandler { - private static final Logger LOG = LoggerFactory.getLogger(RemoteAttestationServerHandler.class); - private byte[] myNonce; - private byte[] yourNonce; - private long sessionID = 0; // used to count messages between ids connectors during attestation - private final URI ttpUri; - private final int attestationMask; - private final IdsAttestationType aType; - private final CertificatePair certificatePair; - private AttestationResponse resp; - - public RemoteAttestationServerHandler( - IdscpConfiguration serverConfiguration, URI ttpUri, String socket) { - // set ttp uri - this.ttpUri = ttpUri; - // set current attestation type and mask (see attestation.proto) - this.aType = serverConfiguration.getAttestationType(); - this.attestationMask = serverConfiguration.getAttestationMask(); - this.certificatePair = serverConfiguration.getCertificatePair(); - } - - public MessageLite enterRatRequest(Event e) { - this.yourNonce = e.getMessage().getAttestationRequest().getNonce().toByteArray(); - // generate a new software nonce on the client and send it to server - this.myNonce = NonceGenerator.generate(20); - // get starting session id - this.sessionID = e.getMessage().getId(); - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.RAT_REQUEST) - .setAttestationRequest( - AttestationRequest.newBuilder() - .setAtype(this.aType) - .setNonce(ByteString.copyFrom(this.myNonce)) - .build()) - .build(); - } - - public MessageLite sendTPM2Ddata(Event e) { - // temporarily save attestation response in order to check it in the result phase - this.resp = e.getMessage().getAttestationResponse(); - final byte[] hash = calculateHash(this.yourNonce, certificatePair.getRemoteCertificate()); - - if (++this.sessionID != e.getMessage().getId()) { - return RemoteAttestationHandler.sendError( - ++this.sessionID, - "error: sessionID not correct ! (is " - + e.getMessage().getId() - + " but should have been " - + (this.sessionID + 1) - + ")"); - } - - String halg = ""; - ByteString quoted = ByteString.EMPTY; - ByteString signature = ByteString.EMPTY; - List pcrValues = Collections.emptyList(); - ByteString certificate = ByteString.EMPTY; - if (tpm2dSocket != null) { - try { - RemoteToTpm2d.Builder msgBuilder = - RemoteToTpm2d.newBuilder() - .setAtype(this.aType) - .setQualifyingData(ByteString.copyFrom(hash)) - .setCode(Code.ATTESTATION_REQ) - .setPcrs(this.attestationMask); - if (this.aType.equals(IdsAttestationType.ADVANCED)) { - // send msg to local unix socket with bitmask set - // construct protobuf message to send to local tpm2d via unix socket - msgBuilder.setPcrs(this.attestationMask); - } - Tpm2dToRemote response = tpm2dSocket.requestAttestation(msgBuilder.build()); - LOG.debug("Tpm2dToRemote message: {}", response.toString()); - halg = response.getHalg().name(); - quoted = response.getQuoted(); - signature = response.getSignature(); - pcrValues = response.getPcrValuesList(); - certificate = response.getCertificate(); - } catch (IOException ex) { - lastError = "IOException during communication with tpm2d: " + ex.getMessage(); - LOG.error(lastError, ex); - } - } else { - LOG.warn("Tpm2dSocket is not available. No TPM present?"); - } - - // now return values from answer to server - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.RAT_RESPONSE) - .setAttestationResponse( - AttestationResponse.newBuilder() - .setAtype(this.aType) - .setHalg(halg) - .setQuoted(quoted) - .setSignature(signature) - .addAllPcrValues(pcrValues) - .setCertificate(certificate) - .build()) - .build(); - } - - public MessageLite sendResult(Event e) { - final byte[] hash = calculateHash(this.myNonce, certificatePair.getLocalCertificate()); - - if (++this.sessionID == e.getMessage().getId()) { - if (this.checkSignature(this.resp, hash) && checkRepository(this.aType, this.resp, ttpUri)) { - this.mySuccess = true; - } else { - lastError = "error: signature check not ok"; - } - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.RAT_RESULT) - .setAttestationResult( - AttestationResult.newBuilder().setAtype(this.aType).setResult(this.mySuccess).build()) - .build(); - } else { - lastError = - "error: sessionID not correct ! (is " - + e.getMessage().getId() - + " but should have been " - + (this.sessionID + 1) - + ")"; - } - LOG.debug(lastError); - return RemoteAttestationHandler.sendError(++this.sessionID, RemoteAttestationHandler.lastError); - } - - public MessageLite leaveRatRequest(Event e) { - this.yourSuccess = e.getMessage().getAttestationResult().getResult(); - - if (++this.sessionID == e.getMessage().getId()) { - return ConnectorMessage.newBuilder() - .setId(++this.sessionID) - .setType(ConnectorMessage.Type.RAT_LEAVE) - .setAttestationLeave(AttestationLeave.newBuilder().setAtype(this.aType).build()) - .build(); - } - lastError = - "error: sessionID not correct ! (is " - + e.getMessage().getId() - + " but should have been " - + (this.sessionID + 1) - + ")"; - LOG.debug(lastError); - return RemoteAttestationHandler.sendError(++this.sessionID, RemoteAttestationHandler.lastError); - } -} diff --git a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/Tpm2dSocket.java b/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/Tpm2dSocket.java deleted file mode 100644 index e077eefc0..000000000 --- a/ids-comm/src/main/java/de/fhg/aisec/ids/comm/ws/protocol/rat/Tpm2dSocket.java +++ /dev/null @@ -1,50 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm.ws.protocol.rat; - -import de.fhg.aisec.ids.messages.AttestationProtos.RemoteToTpm2d; -import de.fhg.aisec.ids.messages.AttestationProtos.Tpm2dToRemote; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.Socket; - -public class Tpm2dSocket extends Socket { - - private final DataInputStream is; - private final DataOutputStream os; - - public Tpm2dSocket(String host) throws IOException { - super(host, 9505); - is = new DataInputStream(this.getInputStream()); - os = new DataOutputStream(this.getOutputStream()); - } - - public Tpm2dToRemote requestAttestation(RemoteToTpm2d request) throws IOException { - // Write attestation request message - byte[] requestBytes = request.toByteArray(); - os.writeInt(requestBytes.length); - os.write(requestBytes); - // Read attestation result message - byte[] resultBytes = new byte[is.readInt()]; - is.readFully(resultBytes); - return Tpm2dToRemote.parseFrom(resultBytes); - } -} diff --git a/ids-comm/src/test/java/de/fhg/aisec/ids/camel/ids/protocol/ADVANCEDAttestationIT.java b/ids-comm/src/test/java/de/fhg/aisec/ids/camel/ids/protocol/ADVANCEDAttestationIT.java deleted file mode 100644 index a2646bea3..000000000 --- a/ids-comm/src/test/java/de/fhg/aisec/ids/camel/ids/protocol/ADVANCEDAttestationIT.java +++ /dev/null @@ -1,228 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.protocol; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import de.fhg.aisec.ids.comm.CertificatePair; -import de.fhg.aisec.ids.comm.client.ClientConfiguration; -import de.fhg.aisec.ids.comm.server.ServerConfiguration; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationClientHandler; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationServerHandler; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import tss.tpm.TPM_ALG_ID; - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -// ADVANCED test with PCRS 0-19 i.e. bitmask is 20 -public class ADVANCEDAttestationIT { - - private static final String TPMD_SOCKET = "socket/control.sock"; - private static RemoteAttestationClientHandler consumer; - private static RemoteAttestationServerHandler provider; - private static Logger LOG = LoggerFactory.getLogger(ADVANCEDAttestationIT.class); - private long id = 87654321; - private static IdsAttestationType aType = IdsAttestationType.ADVANCED; - private static int bitmask = 20; - - private TPM_ALG_ID hAlg = TPM_ALG_ID.SHA256; - - private ConnectorMessage msg0 = - ConnectorMessage.newBuilder().setType(ConnectorMessage.Type.RAT_START).setId(id).build(); - - private static ConnectorMessage msg1; - private static ConnectorMessage msg2; - private static ConnectorMessage msg3; - private static ConnectorMessage msg4; - private static ConnectorMessage msg5; - private static ConnectorMessage msg6; - private static ConnectorMessage msg7; - private static ConnectorMessage msg8; - - @BeforeClass - public static void initHandlers() throws URISyntaxException, CertificateEncodingException { - // Certificate mocks for server and client - Certificate clientDummyCert = mock(Certificate.class); - when(clientDummyCert.getEncoded()).thenReturn(new byte[] {0x0}); - Certificate serverDummyCert = mock(Certificate.class); - when(serverDummyCert.getEncoded()).thenReturn(new byte[] {0x1}); - // Client IDSCP configuration - CertificatePair clientPair = new CertificatePair(); - clientPair.setLocalCertificate(clientDummyCert); - clientPair.setRemoteCertificate(serverDummyCert); - ClientConfiguration clientConfiguration = - new ClientConfiguration.Builder() - .attestationType(aType) - .certificatePair(clientPair) - .build(); - // Server IDSCP configuration - CertificatePair serverPair = new CertificatePair(); - serverPair.setLocalCertificate(serverDummyCert); - serverPair.setRemoteCertificate(clientDummyCert); - ServerConfiguration serverConfiguration = - new ServerConfiguration.Builder() - .attestationType(aType) - .certificatePair(serverPair) - .attestationMask(bitmask) - .build(); - final String ratRepoUri = "https://127.0.0.1:31337/configurations/check"; - consumer = - new RemoteAttestationClientHandler(clientConfiguration, new URI(ratRepoUri), TPMD_SOCKET); - provider = - new RemoteAttestationServerHandler(serverConfiguration, new URI(ratRepoUri), TPMD_SOCKET); - } - - @Test - public void test1() throws Exception { - msg1 = - ConnectorMessage.parseFrom( - consumer - .enterRatRequest(new Event(msg0.getType(), msg0.toString(), msg0)) - .toByteString()); - LOG.debug(msg1.toString()); - assertTrue(msg1.getId() == id + 1); - assertTrue(msg1.getType().equals(ConnectorMessage.Type.RAT_REQUEST)); - } - - @Test - public void test2() throws Exception { - msg2 = - ConnectorMessage.parseFrom( - provider - .enterRatRequest(new Event(msg1.getType(), msg1.toString(), msg1)) - .toByteString()); - LOG.debug(msg2.toString()); - assertTrue(msg2.getId() == id + 2); - assertTrue(msg2.getType().equals(ConnectorMessage.Type.RAT_REQUEST)); - } - - @Test - public void test3() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg3 = - ConnectorMessage.parseFrom( - consumer - .sendTPM2Ddata(new Event(msg2.getType(), msg2.toString(), msg2)) - .toByteString()); - LOG.debug(msg3.toString()); - assertTrue(msg3.getId() == id + 3); - assertTrue(msg3.getType().equals(ConnectorMessage.Type.RAT_RESPONSE)); - assertTrue(msg3.getAttestationResponse().getAtype().equals(aType)); - assertTrue(msg3.getAttestationResponse().getHalg().equals(hAlg.name())); - assertTrue(msg3.getAttestationResponse().getPcrValuesCount() == bitmask); - } - - @Test - public void test4() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg4 = - ConnectorMessage.parseFrom( - provider - .sendTPM2Ddata(new Event(msg3.getType(), msg3.toString(), msg3)) - .toByteString()); - LOG.debug(msg4.toString()); - assertTrue(msg4.getId() == id + 4); - assertTrue(msg4.getType().equals(ConnectorMessage.Type.RAT_RESPONSE)); - assertTrue(msg4.getAttestationResponse().getAtype().equals(aType)); - assertTrue(msg4.getAttestationResponse().getHalg().equals(hAlg.name())); - assertTrue(msg4.getAttestationResponse().getPcrValuesCount() == bitmask); - } - - @Test - public void test5() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg5 = - ConnectorMessage.parseFrom( - consumer.sendResult(new Event(msg4.getType(), msg4.toString(), msg4)).toByteString()); - LOG.debug(msg5.toString()); - assertTrue(msg5.getId() == id + 5); - assertTrue(msg5.getType().equals(ConnectorMessage.Type.RAT_RESULT)); - assertTrue(msg5.getAttestationResult().getResult()); - assertTrue(msg5.getAttestationResult().getAtype().equals(aType)); - } - - @Test - public void test6() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg6 = - ConnectorMessage.parseFrom( - provider.sendResult(new Event(msg5.getType(), msg5.toString(), msg5)).toByteString()); - LOG.debug(msg6.toString()); - assertTrue(msg6.getId() == id + 6); - assertTrue(msg6.getType().equals(ConnectorMessage.Type.RAT_RESULT)); - assertTrue(msg6.getAttestationResult().getResult()); - assertTrue(msg6.getAttestationResult().getAtype().equals(aType)); - } - - @Test - public void test7() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg7 = - ConnectorMessage.parseFrom( - consumer - .leaveRatRequest(new Event(msg6.getType(), msg6.toString(), msg6)) - .toByteString()); - LOG.debug(msg7.toString()); - assertTrue(msg7.getId() == id + 7); - assertTrue(msg7.getType().equals(ConnectorMessage.Type.RAT_LEAVE)); - assertTrue(msg7.getAttestationLeave().getAtype().equals(aType)); - } - - @Test - public void test8() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg8 = - ConnectorMessage.parseFrom( - provider - .leaveRatRequest(new Event(msg7.getType(), msg7.toString(), msg7)) - .toByteString()); - LOG.debug(msg8.toString()); - assertTrue(msg8.getId() == id + 8); - assertTrue(msg8.getType().equals(ConnectorMessage.Type.RAT_LEAVE)); - assertTrue(msg8.getAttestationLeave().getAtype().equals(aType)); - } -} diff --git a/ids-comm/src/test/java/de/fhg/aisec/ids/camel/ids/protocol/ALLAttestationIT.java b/ids-comm/src/test/java/de/fhg/aisec/ids/camel/ids/protocol/ALLAttestationIT.java deleted file mode 100644 index cebbc8c8d..000000000 --- a/ids-comm/src/test/java/de/fhg/aisec/ids/camel/ids/protocol/ALLAttestationIT.java +++ /dev/null @@ -1,227 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.protocol; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import de.fhg.aisec.ids.comm.CertificatePair; -import de.fhg.aisec.ids.comm.client.ClientConfiguration; -import de.fhg.aisec.ids.comm.server.ServerConfiguration; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationClientHandler; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationServerHandler; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import tss.tpm.TPM_ALG_ID; - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -// ALL test with PCRS 0-23 -public class ALLAttestationIT { - - private static final String TPMD_SOCKET = "socket/control.sock"; - private static RemoteAttestationClientHandler consumer; - private static RemoteAttestationServerHandler provider; - private static Logger LOG = LoggerFactory.getLogger(ALLAttestationIT.class); - private long id = 87654321; - private static IdsAttestationType aType = IdsAttestationType.ALL; - - private TPM_ALG_ID hAlg = TPM_ALG_ID.SHA256; - - private ConnectorMessage msg0 = - ConnectorMessage.newBuilder().setType(ConnectorMessage.Type.RAT_START).setId(id).build(); - private static ConnectorMessage msg1; - private static ConnectorMessage msg2; - private static ConnectorMessage msg3; - private static ConnectorMessage msg4; - private static ConnectorMessage msg5; - private static ConnectorMessage msg6; - private static ConnectorMessage msg7; - private static ConnectorMessage msg8; - - @BeforeClass - public static void initHandlers() throws URISyntaxException, CertificateEncodingException { - // Certificate mocks for server and client - Certificate clientDummyCert = mock(Certificate.class); - when(clientDummyCert.getEncoded()).thenReturn(new byte[] {0x0, 0x0, 0x0, 0x0}); - Certificate serverDummyCert = mock(Certificate.class); - when(serverDummyCert.getEncoded()).thenReturn(new byte[] {0x1, 0x1, 0x1, 0x1}); - // Client IDSCP configuration - CertificatePair clientPair = new CertificatePair(); - clientPair.setLocalCertificate(clientDummyCert); - clientPair.setRemoteCertificate(serverDummyCert); - ClientConfiguration clientConfiguration = - new ClientConfiguration.Builder() - .attestationType(aType) - .certificatePair(clientPair) - .build(); - // Server IDSCP configuration - CertificatePair serverPair = new CertificatePair(); - serverPair.setLocalCertificate(serverDummyCert); - serverPair.setRemoteCertificate(clientDummyCert); - ServerConfiguration serverConfiguration = - new ServerConfiguration.Builder() - .attestationType(aType) - .certificatePair(serverPair) - .build(); - final String ratRepoUri = "https://127.0.0.1:31337/configurations/check"; - consumer = - new RemoteAttestationClientHandler(clientConfiguration, new URI(ratRepoUri), TPMD_SOCKET); - provider = - new RemoteAttestationServerHandler(serverConfiguration, new URI(ratRepoUri), TPMD_SOCKET); - } - - @Test - public void test1() throws Exception { - msg1 = - ConnectorMessage.parseFrom( - consumer - .enterRatRequest(new Event(msg0.getType(), msg0.toString(), msg0)) - .toByteString()); - LOG.debug(msg1.toString()); - assertTrue(msg1.getId() == id + 1); - assertTrue(msg1.getType().equals(ConnectorMessage.Type.RAT_REQUEST)); - } - - @Test - public void test2() throws Exception { - msg2 = - ConnectorMessage.parseFrom( - provider - .enterRatRequest(new Event(msg1.getType(), msg1.toString(), msg1)) - .toByteString()); - LOG.debug(msg2.toString()); - assertTrue(msg2.getId() == id + 2); - assertTrue(msg2.getType().equals(ConnectorMessage.Type.RAT_REQUEST)); - } - - @Test - public void test3() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg3 = - ConnectorMessage.parseFrom( - consumer - .sendTPM2Ddata(new Event(msg2.getType(), msg2.toString(), msg2)) - .toByteString()); - LOG.debug(msg3.toString()); - assertTrue(msg3.getId() == id + 3); - assertTrue(msg3.getType().equals(ConnectorMessage.Type.RAT_RESPONSE)); - assertTrue(msg3.getAttestationResponse().getAtype().equals(aType)); - assertTrue(msg3.getAttestationResponse().getHalg().equals(hAlg.name())); - assertTrue(msg3.getAttestationResponse().getPcrValuesCount() == 24); - } - - @Test - public void test4() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg4 = - ConnectorMessage.parseFrom( - provider - .sendTPM2Ddata(new Event(msg3.getType(), msg3.toString(), msg3)) - .toByteString()); - LOG.debug(msg4.toString()); - assertTrue(msg4.getId() == id + 4); - assertTrue(msg4.getType().equals(ConnectorMessage.Type.RAT_RESPONSE)); - assertTrue(msg4.getAttestationResponse().getAtype().equals(aType)); - assertTrue(msg4.getAttestationResponse().getHalg().equals(hAlg.name())); - assertTrue(msg4.getAttestationResponse().getPcrValuesCount() == 24); - } - - @Test - public void test5() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg5 = - ConnectorMessage.parseFrom( - consumer.sendResult(new Event(msg4.getType(), msg4.toString(), msg4)).toByteString()); - LOG.debug(msg5.toString()); - assertTrue(msg5.getId() == id + 5); - assertTrue(msg5.getType().equals(ConnectorMessage.Type.RAT_RESULT)); - // commented out until tpm2d is fixed - assertTrue(msg5.getAttestationResult().getResult()); - assertTrue(msg5.getAttestationResult().getAtype().equals(aType)); - } - - @Test - public void test6() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg6 = - ConnectorMessage.parseFrom( - provider.sendResult(new Event(msg5.getType(), msg5.toString(), msg5)).toByteString()); - LOG.debug(msg6.toString()); - assertTrue(msg6.getId() == id + 6); - assertTrue(msg6.getType().equals(ConnectorMessage.Type.RAT_RESULT)); - // commented out until tpm2d is fixed - assertTrue(msg6.getAttestationResult().getResult()); - assertTrue(msg6.getAttestationResult().getAtype().equals(aType)); - } - - @Test - public void test7() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg7 = - ConnectorMessage.parseFrom( - consumer - .leaveRatRequest(new Event(msg6.getType(), msg6.toString(), msg6)) - .toByteString()); - LOG.debug(msg7.toString()); - assertTrue(msg7.getId() == id + 7); - assertTrue(msg7.getType().equals(ConnectorMessage.Type.RAT_LEAVE)); - assertTrue(msg7.getAttestationLeave().getAtype().equals(aType)); - } - - @Test - public void test8() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg8 = - ConnectorMessage.parseFrom( - provider - .leaveRatRequest(new Event(msg7.getType(), msg7.toString(), msg7)) - .toByteString()); - LOG.debug(msg8.toString()); - assertTrue(msg8.getId() == id + 8); - assertTrue(msg8.getType().equals(ConnectorMessage.Type.RAT_LEAVE)); - assertTrue(msg8.getAttestationLeave().getAtype().equals(aType)); - } -} diff --git a/ids-comm/src/test/java/de/fhg/aisec/ids/camel/ids/protocol/BASICAttestationIT.java b/ids-comm/src/test/java/de/fhg/aisec/ids/camel/ids/protocol/BASICAttestationIT.java deleted file mode 100644 index 1ebb4fe3a..000000000 --- a/ids-comm/src/test/java/de/fhg/aisec/ids/camel/ids/protocol/BASICAttestationIT.java +++ /dev/null @@ -1,225 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.camel.ids.protocol; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import de.fhg.aisec.ids.comm.CertificatePair; -import de.fhg.aisec.ids.comm.client.ClientConfiguration; -import de.fhg.aisec.ids.comm.server.ServerConfiguration; -import de.fhg.aisec.ids.comm.ws.protocol.fsm.Event; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationClientHandler; -import de.fhg.aisec.ids.comm.ws.protocol.rat.RemoteAttestationServerHandler; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import de.fhg.aisec.ids.messages.Idscp.ConnectorMessage; -import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import tss.tpm.TPM_ALG_ID; - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -// BASIC test -public class BASICAttestationIT { - private static final String TPMD_SOCKET = "socket/control.sock"; - private static RemoteAttestationClientHandler consumer; - private static RemoteAttestationServerHandler provider; - private static Logger LOG = LoggerFactory.getLogger(BASICAttestationIT.class); - private long id = 87654321; - private static IdsAttestationType aType = IdsAttestationType.BASIC; - - private TPM_ALG_ID hAlg = TPM_ALG_ID.SHA256; - - private ConnectorMessage msg0 = - ConnectorMessage.newBuilder().setType(ConnectorMessage.Type.RAT_START).setId(id).build(); - - private static ConnectorMessage msg1; - private static ConnectorMessage msg2; - private static ConnectorMessage msg3; - private static ConnectorMessage msg4; - private static ConnectorMessage msg5; - private static ConnectorMessage msg6; - private static ConnectorMessage msg7; - private static ConnectorMessage msg8; - - @BeforeClass - public static void initHandlers() throws URISyntaxException, CertificateEncodingException { - // Certificate mocks for server and client - Certificate clientDummyCert = mock(Certificate.class); - when(clientDummyCert.getEncoded()).thenReturn(new byte[] {0x0, 0x0, 0x0, 0x0}); - Certificate serverDummyCert = mock(Certificate.class); - when(serverDummyCert.getEncoded()).thenReturn(new byte[] {0x1, 0x1, 0x1, 0x1}); - // Client IDSCP configuration - CertificatePair clientPair = new CertificatePair(); - clientPair.setLocalCertificate(clientDummyCert); - clientPair.setRemoteCertificate(serverDummyCert); - ClientConfiguration clientConfiguration = - new ClientConfiguration.Builder() - .attestationType(aType) - .certificatePair(clientPair) - .build(); - // Server IDSCP configuration - CertificatePair serverPair = new CertificatePair(); - serverPair.setLocalCertificate(serverDummyCert); - serverPair.setRemoteCertificate(clientDummyCert); - ServerConfiguration serverConfiguration = - new ServerConfiguration.Builder() - .attestationType(aType) - .certificatePair(serverPair) - .build(); - final String ratRepoUri = "https://127.0.0.1:31337/configurations/check"; - consumer = - new RemoteAttestationClientHandler(clientConfiguration, new URI(ratRepoUri), TPMD_SOCKET); - provider = - new RemoteAttestationServerHandler(serverConfiguration, new URI(ratRepoUri), TPMD_SOCKET); - } - - @Test - public void test1() throws Exception { - msg1 = - ConnectorMessage.parseFrom( - consumer - .enterRatRequest(new Event(msg0.getType(), msg0.toString(), msg0)) - .toByteString()); - LOG.debug(msg1.toString()); - assertTrue(msg1.getId() == id + 1); - assertTrue(msg1.getType().equals(ConnectorMessage.Type.RAT_REQUEST)); - } - - @Test - public void test2() throws Exception { - msg2 = - ConnectorMessage.parseFrom( - provider - .enterRatRequest(new Event(msg1.getType(), msg1.toString(), msg1)) - .toByteString()); - LOG.debug(msg2.toString()); - assertTrue(msg2.getId() == id + 2); - assertTrue(msg2.getType().equals(ConnectorMessage.Type.RAT_REQUEST)); - } - - @Test - public void test3() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg3 = - ConnectorMessage.parseFrom( - consumer - .sendTPM2Ddata(new Event(msg2.getType(), msg2.toString(), msg2)) - .toByteString()); - LOG.debug(msg3.toString()); - assertTrue(msg3.getId() == id + 3); - assertTrue(msg3.getType().equals(ConnectorMessage.Type.RAT_RESPONSE)); - assertTrue(msg3.getAttestationResponse().getAtype().equals(aType)); - assertTrue(msg3.getAttestationResponse().getHalg().equals(hAlg.name())); - assertTrue(msg3.getAttestationResponse().getPcrValuesCount() == 11); - } - - @Test - public void test4() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg4 = - ConnectorMessage.parseFrom( - provider - .sendTPM2Ddata(new Event(msg3.getType(), msg3.toString(), msg3)) - .toByteString()); - LOG.debug(msg4.toString()); - assertTrue(msg4.getId() == id + 4); - assertTrue(msg4.getType().equals(ConnectorMessage.Type.RAT_RESPONSE)); - assertTrue(msg4.getAttestationResponse().getAtype().equals(aType)); - assertTrue(msg4.getAttestationResponse().getHalg().equals(hAlg.name())); - assertTrue(msg4.getAttestationResponse().getPcrValuesCount() == 11); - } - - @Test - public void test5() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg5 = - ConnectorMessage.parseFrom( - consumer.sendResult(new Event(msg4.getType(), msg4.toString(), msg4)).toByteString()); - LOG.debug(msg5.toString()); - assertTrue(msg5.getId() == id + 5); - assertTrue(msg5.getType().equals(ConnectorMessage.Type.RAT_RESULT)); - assertTrue(msg5.getAttestationResult().getResult()); - assertTrue(msg5.getAttestationResult().getAtype().equals(aType)); - } - - @Test - public void test6() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg6 = - ConnectorMessage.parseFrom( - provider.sendResult(new Event(msg5.getType(), msg5.toString(), msg5)).toByteString()); - LOG.debug(msg6.toString()); - assertTrue(msg6.getId() == id + 6); - assertTrue(msg6.getType().equals(ConnectorMessage.Type.RAT_RESULT)); - assertTrue(msg6.getAttestationResult().getResult()); - assertTrue(msg6.getAttestationResult().getAtype().equals(aType)); - } - - @Test - public void test7() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg7 = - ConnectorMessage.parseFrom( - consumer - .leaveRatRequest(new Event(msg6.getType(), msg6.toString(), msg6)) - .toByteString()); - LOG.debug(msg7.toString()); - assertTrue(msg7.getId() == id + 7); - assertTrue(msg7.getType().equals(ConnectorMessage.Type.RAT_LEAVE)); - assertTrue(msg7.getAttestationLeave().getAtype().equals(aType)); - } - - @Test - public void test8() throws Exception { - assumeTrue( - "tpmd socket not available. Skipping integration test", new File(TPMD_SOCKET).canWrite()); - - msg8 = - ConnectorMessage.parseFrom( - provider - .leaveRatRequest(new Event(msg7.getType(), msg7.toString(), msg7)) - .toByteString()); - LOG.debug(msg8.toString()); - assertTrue(msg8.getId() == id + 8); - assertTrue(msg8.getType().equals(ConnectorMessage.Type.RAT_LEAVE)); - assertTrue(msg8.getAttestationLeave().getAtype().equals(aType)); - } -} diff --git a/ids-comm/src/test/java/de/fhg/aisec/ids/comm/EventSocket.java b/ids-comm/src/test/java/de/fhg/aisec/ids/comm/EventSocket.java deleted file mode 100644 index 78918e453..000000000 --- a/ids-comm/src/test/java/de/fhg/aisec/ids/comm/EventSocket.java +++ /dev/null @@ -1,49 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm; - -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.WebSocketAdapter; - -public class EventSocket extends WebSocketAdapter { - @Override - public void onWebSocketConnect(Session sess) { - super.onWebSocketConnect(sess); - System.out.println("Socket Connected: " + sess); - } - - @Override - public void onWebSocketText(String message) { - super.onWebSocketText(message); - System.out.println("Received TEXT message: " + message); - } - - @Override - public void onWebSocketClose(int statusCode, String reason) { - super.onWebSocketClose(statusCode, reason); - System.out.println("Socket Closed: [" + statusCode + "] " + reason); - } - - @Override - public void onWebSocketError(Throwable cause) { - super.onWebSocketError(cause); - cause.printStackTrace(System.err); - } -} diff --git a/ids-comm/src/test/java/de/fhg/aisec/ids/comm/MySocketListener.java b/ids-comm/src/test/java/de/fhg/aisec/ids/comm/MySocketListener.java deleted file mode 100644 index 3be30390f..000000000 --- a/ids-comm/src/test/java/de/fhg/aisec/ids/comm/MySocketListener.java +++ /dev/null @@ -1,52 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm; - -import de.fhg.aisec.ids.comm.server.IdscpServerSocket; -import de.fhg.aisec.ids.comm.server.SocketListener; -import org.eclipse.jetty.websocket.api.Session; - -class MySocketListener implements SocketListener { - private String lastMsg = null; - - @Override - public synchronized void onMessage(Session session, byte[] msg) { - // Wake Thread(s) that called getLastMsg() - this.notifyAll(); - this.lastMsg = new String(msg); - } - - synchronized String getLastMsg() { - // If message is null, we wait for asynchronous delivery - if (this.lastMsg == null) { - try { - this.wait(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - return this.lastMsg; - } - - @Override - public void notifyClosed(IdscpServerSocket idscpServerSocket) { - // Nothing to do here. Socket is already closed. - } -} diff --git a/ids-comm/src/test/java/de/fhg/aisec/ids/comm/ProtocolTest.java b/ids-comm/src/test/java/de/fhg/aisec/ids/comm/ProtocolTest.java deleted file mode 100644 index e02efa5d5..000000000 --- a/ids-comm/src/test/java/de/fhg/aisec/ids/comm/ProtocolTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-comm - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.comm; - -import static org.junit.Assert.*; - -import de.fhg.aisec.ids.api.conm.RatResult; -import de.fhg.aisec.ids.comm.client.ClientConfiguration; -import de.fhg.aisec.ids.comm.client.IdscpClient; -import de.fhg.aisec.ids.comm.server.IdscpServer; -import de.fhg.aisec.ids.comm.server.ServerConfiguration; -import de.fhg.aisec.ids.messages.AttestationProtos.IdsAttestationType; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.util.Collections; -import java.util.concurrent.ExecutionException; -import javax.xml.bind.DatatypeConverter; -import org.asynchttpclient.ws.WebSocket; -import org.junit.Test; - -public class ProtocolTest { - - @Test - public void testFailureHandling() - throws InterruptedException, ExecutionException, URISyntaxException, NoSuchAlgorithmException, - KeyStoreException, CertificateException, IOException, KeyManagementException { - final MySocketListener listener = new MySocketListener(); - final Path jssePath = FileSystems.getDefault().getPath("src/test/resources/jsse"); - - final KeyStore ks = KeyStore.getInstance("JKS"); - ks.load( - Files.newInputStream(jssePath.resolve("server-keystore.jks")), "password".toCharArray()); - // Configure and start Server in one fluent call chain and use NON-EXISTING TPM SOCKET. - @SuppressWarnings("unused") - IdscpServer server = - new IdscpServer() - .config( - new ServerConfiguration.Builder() - .port(8081) - .attestationType(IdsAttestationType.BASIC) - .setKeyStore(ks) - .ttpUrl(new URI("https://localhost/nonexistingdummy_ttp")) - .build()) - .setSocketListener(listener) - .start(); - - // Configure and start client (blocks until IDSCP has finished) - IdscpClient client = - new IdscpClient() - .config( - new ClientConfiguration.Builder() - .setSha256CertificateHashes( - Collections.singletonList( - DatatypeConverter.parseHexBinary( - "4439DA49F320E3786319A5CF8D69F3A0831C4801B5CE3A14570EA84E0ECD82B0"))) - .build()); - WebSocket wsClient = client.connect("localhost", 8081); - - // --- IDSC protocol will run automatically now --- - - // Client web socket is now expected to be open - assertTrue(wsClient.isOpen()); - - // Attestation result is expected to be not null and FAIL (because we did not connect to proper - // TPM above) - RatResult attestationResult = client.getAttestationResult(); - assertNotNull(attestationResult); - assertEquals(RatResult.Status.FAILED, attestationResult.getStatus()); - - // TODO Make server-side attestation result accessible - // AttestationResult serverAttestationRes = server.handleAttestationResult(); - - // Send some payload from client to server - wsClient.sendTextFrame("Hello"); - - // Expect server to receive our payload - String serverReceived = listener.getLastMsg(); - assertNotNull(serverReceived); - assertEquals("Hello", serverReceived); - - try { - wsClient.sendCloseFrame(200, "Shutdown"); - } catch (Exception e) { - // ignore - } - try { - server.getServer().stop(); - } catch (Exception e) { - // ignore - } - - // This is how to let the server run forever: - // server.getServer().join(); - } -} diff --git a/ids-comm/src/test/resources/jsse/client-keystore.jks b/ids-comm/src/test/resources/jsse/client-keystore.jks deleted file mode 100644 index 1a296db9f..000000000 Binary files a/ids-comm/src/test/resources/jsse/client-keystore.jks and /dev/null differ diff --git a/ids-comm/src/test/resources/jsse/client-truststore.jks b/ids-comm/src/test/resources/jsse/client-truststore.jks deleted file mode 100644 index eebd40f4c..000000000 Binary files a/ids-comm/src/test/resources/jsse/client-truststore.jks and /dev/null differ diff --git a/ids-comm/src/test/resources/jsse/server-keystore.jks b/ids-comm/src/test/resources/jsse/server-keystore.jks deleted file mode 100644 index 5e8f8003f..000000000 Binary files a/ids-comm/src/test/resources/jsse/server-keystore.jks and /dev/null differ diff --git a/ids-comm/src/test/resources/jsse/server-truststore.jks b/ids-comm/src/test/resources/jsse/server-truststore.jks deleted file mode 100644 index 839915521..000000000 Binary files a/ids-comm/src/test/resources/jsse/server-truststore.jks and /dev/null differ diff --git a/ids-container-manager/build.gradle b/ids-container-manager/build.gradle deleted file mode 100644 index 7b9c925d9..000000000 --- a/ids-container-manager/build.gradle +++ /dev/null @@ -1,40 +0,0 @@ -apply plugin: 'com.google.protobuf' -apply plugin: 'idea' - -protobuf { - generatedFilesBaseDir = "$projectDir/generated" -} - -clean { - delete protobuf.generatedFilesBaseDir -} - -idea { - module { - // mark as generated sources for IDEA - generatedSourceDirs += file("${protobuf.generatedFilesBaseDir}/main/java") - } -} - -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - // Provided dependency of docker-java-api - providedByBundle group: 'org.glassfish', name: 'javax.json', version: libraryVersions.javaxJson - // Required until our library PR has been accepted - providedByBundle(group: 'com.amihaiemil.web', name: 'docker-java-api', version: libraryVersions.dockerJavaApi) { - exclude group: 'com.github.jnr', module: 'jnr-unixsocket' - } - - compileOnly project(":jnr-unixsocket-wrapper") - - providedByBundle group: 'com.google.protobuf', name: 'protobuf-java', version: libraryVersions.protobuf - - osgiCore group: 'org.osgi', name: 'osgi.cmpn', version: libraryVersions.osgiCompendium - - testImplementation group: 'junit', name: 'junit', version: libraryVersions.junit4 - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito -} diff --git a/ids-container-manager/build.gradle.kts b/ids-container-manager/build.gradle.kts new file mode 100644 index 000000000..92875d3fd --- /dev/null +++ b/ids-container-manager/build.gradle.kts @@ -0,0 +1,51 @@ +import com.google.protobuf.gradle.protobuf +import org.gradle.plugins.ide.idea.model.IdeaModel + +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map + +apply(plugin = "com.google.protobuf") +apply(plugin = "idea") + +val protobufGeneratedDir = "$projectDir/generated" + +protobuf { + generatedFilesBaseDir = protobufGeneratedDir +} + +tasks.clean { + doFirst { + delete(protobufGeneratedDir) + } + // Sometimes required to fix an error caused by a non-existing folder + doLast { + mkdir("${project.buildDir}/classes/kotlin/main") + } +} + +configure { + module { + // mark as generated sources for IDEA + generatedSourceDirs.add(File("${protobufGeneratedDir}/main/java")) + } +} + +dependencies { + providedByBundle(project(":ids-api")) { isTransitive = false } + + // Provided dependency of docker-java-api + providedByBundle("org.glassfish", "javax.json", libraryVersions["javaxJson"]) + // Required until our library PR has been accepted + providedByBundle("com.amihaiemil.web", "docker-java-api", libraryVersions["dockerJavaApi"]) { + exclude("com.github.jnr", "jnr-unixsocket") + } + + implementation(project(":jnr-unixsocket-wrapper")) + + providedByBundle("com.google.protobuf", "protobuf-java", libraryVersions["protobuf"]) + + osgiCore("org.osgi", "osgi.cmpn", libraryVersions["osgiCompendium"]) + + testImplementation("junit", "junit", libraryVersions["junit4"]) + testImplementation("org.mockito", "mockito-core", libraryVersions["mockito"]) +} diff --git a/ids-container-manager/src/main/java/de/fhg/aisec/ids/cm/impl/docker/DockerCM.kt b/ids-container-manager/src/main/java/de/fhg/aisec/ids/cm/impl/docker/DockerCM.kt index 7cadd5c06..4e83dc66a 100644 --- a/ids-container-manager/src/main/java/de/fhg/aisec/ids/cm/impl/docker/DockerCM.kt +++ b/ids-container-manager/src/main/java/de/fhg/aisec/ids/cm/impl/docker/DockerCM.kt @@ -21,25 +21,20 @@ package de.fhg.aisec.ids.cm.impl.docker import com.amihaiemil.docker.Container import com.amihaiemil.docker.Docker -import com.amihaiemil.docker.Image +import com.amihaiemil.docker.Images import com.amihaiemil.docker.LocalDocker import de.fhg.aisec.ids.api.cm.* -import org.slf4j.LoggerFactory import java.io.File import java.io.IOException +import java.net.InetAddress import java.time.* import java.time.temporal.ChronoUnit import java.time.temporal.TemporalUnit import java.util.* import java.util.stream.Collectors -import java.util.stream.Stream -import java.util.stream.StreamSupport -import javax.json.Json -import javax.json.JsonArray -import javax.json.JsonString -import javax.json.JsonValue +import javax.json.* import kotlin.math.abs - +import org.slf4j.LoggerFactory /** * ContainerManager implementation for Docker containers. @@ -51,8 +46,10 @@ class DockerCM : ContainerManager { companion object { private val LOG = LoggerFactory.getLogger(DockerCM::class.java) private lateinit var DOCKER_CLIENT: Docker - private val PERIOD_UNITS = listOf(ChronoUnit.YEARS, ChronoUnit.MONTHS, ChronoUnit.DAYS) - private val DURATION_UNITS = listOf(ChronoUnit.HOURS, ChronoUnit.MINUTES, ChronoUnit.SECONDS) + private val PERIOD_UNITS = + listOf(ChronoUnit.YEARS, ChronoUnit.MONTHS, ChronoUnit.DAYS) + private val DURATION_UNITS = + listOf(ChronoUnit.HOURS, ChronoUnit.MINUTES, ChronoUnit.SECONDS) /** * Returns true if Docker is supported. * @@ -63,8 +60,9 @@ class DockerCM : ContainerManager { return try { DOCKER_CLIENT.ping() } catch (e: Exception) { - when(e) { - is UninitializedPropertyAccessException -> LOG.warn("Docker client is not available") + when (e) { + is UninitializedPropertyAccessException -> + LOG.warn("Docker client is not available") else -> LOG.error(e.message, e) } false @@ -72,7 +70,8 @@ class DockerCM : ContainerManager { } init { - try { // We have to modify the thread class loader for docker-java-api to find its config + try { // We have to modify the thread class loader for docker-java-api to find its + // config val threadContextClassLoader = Thread.currentThread().contextClassLoader Thread.currentThread().contextClassLoader = LocalDocker::class.java.classLoader DOCKER_CLIENT = LocalDocker(File("/var/run/docker.sock")) @@ -83,8 +82,7 @@ class DockerCM : ContainerManager { } /** - * Human readable memory sizes - * Credits: aioobe, https://stackoverflow.com/questions + * Human readable memory sizes Credits: aioobe, https://stackoverflow.com/questions * /3758606/how-to-convert-byte-size-into-human-readable-format-in-java */ private fun humanReadableByteCount(bytes: Long): String? { @@ -136,105 +134,143 @@ class DockerCM : ContainerManager { } } - private fun getContainerStream( - all: Boolean = false, - filters: Map>? = null, - withSize: Boolean = false): Stream { - val filteredContainers = DOCKER_CLIENT - .containers() - .filter(filters ?: emptyMap()) - .withSize(withSize) - return StreamSupport.stream( - Spliterators.spliteratorUnknownSize( - if (all) filteredContainers.all() else filteredContainers.iterator(), - Spliterator.ORDERED - ), false) + private fun getContainerSequence( + all: Boolean = false, + filters: Map>? = null, + withSize: Boolean = false + ): Sequence { + val filteredContainers = + DOCKER_CLIENT.containers().filter(filters ?: emptyMap()).withSize(withSize) + return if (all) { + filteredContainers.all().asSequence() + } else { + filteredContainers.iterator().asSequence() + } } - private fun getImageStream(filters: Map>?): Stream { - return StreamSupport.stream( - Spliterators.spliteratorUnknownSize( - DOCKER_CLIENT - .images() - .filter(filters ?: emptyMap()).iterator(), - Spliterator.ORDERED - ), false) + private fun getImages(filters: Map>?): Images { + return DOCKER_CLIENT.images().filter(filters ?: emptyMap()) } override fun list(onlyRunning: Boolean): List { - return getContainerStream(true, withSize = true).map { c: Container -> - try { - val info = c.inspect() - val state = info.getJsonObject("State") - val config = info.getJsonObject("Config") - val running = state.getBoolean("Running") - val startedAt = state.getString("StartedAt") - val name = info.getString("Name").substring(1) - val ports = info.getJsonObject("NetworkSettings").getJsonObject("Ports") - val labels = config.getJsonObject("Labels") - val app = ApplicationContainer() - app.id = c.containerId() - app.image = config.getString("Image") - app.size = "${humanReadableByteCount((c["SizeRw"] ?: 0).toString().toLong())} RW (data), " + - "${humanReadableByteCount((c["SizeRootFs"] ?: 0).toString().toLong())} RO (layers)" - app.created = info.getString("Created") - app.status = ContainerStatus.valueOf(state.getString("Status").toUpperCase()) - app.ports = ports.entries - .map { e: Map.Entry -> - if (e.value is JsonArray) { - e.key + " -> " + e.value.asJsonArray()[0].asJsonObject().let { - (it["HostIp"] as JsonString).string + ":" + (it["HostPort"] as JsonString).string + return getContainerSequence(!onlyRunning, withSize = true) + .map { c: Container -> + try { + val info = c.inspect() + val imageInfo = getImage(c)?.inspect() + val state = info.getJsonObject("State") + val config = info.getJsonObject("Config") + val running = state.getBoolean("Running") + val startedAt = state.getString("StartedAt") + val name = info.getString("Name").substring(1) + val networkSettings = info.getJsonObject("NetworkSettings") + val networks = networkSettings.getJsonObject("Networks") + val ports = networkSettings.getJsonObject("Ports") + val labels = config.getJsonObject("Labels") + val app = ApplicationContainer() + app.id = c.containerId() + app.image = config.getString("Image") + app.imageId = imageInfo?.getString("Id") + app.imageDigests = + imageInfo?.getJsonArray("RepoDigests")?.map { (it as JsonString).string } + ?: emptyList() + app.ipAddresses = + networks + .values + .mapNotNull { + val ip = (it as JsonObject).getString("IPAddress") + try { + if (ip != null && ip.isNotEmpty()) { + InetAddress.getByName(ip) + } else { + null + } + } catch (x: Exception) { + LOG.warn("Error while resolving ip address \"$ip\"", x) + null } - } else { - e.key } - } - .toList() - app.names = name - if (running) { - app.uptime = formatDuration( - ZonedDateTime.parse(startedAt), OffsetDateTime.now(ZoneId.of("Z")).toZonedDateTime()) - } else { - app.uptime = "-" + .toList() + app.size = + "${humanReadableByteCount((c["SizeRw"] ?: 0).toString().toLong())} RW (data), " + + "${humanReadableByteCount((c["SizeRootFs"] ?: 0).toString().toLong())} RO (layers)" + app.created = info.getString("Created") + app.status = ContainerStatus.valueOf(state.getString("Status").toUpperCase()) + app.ports = + ports + .entries + .map { e: Map.Entry -> + if (e.value is JsonArray) { + e.key + + " -> " + + e.value.asJsonArray()[0].asJsonObject().let { + (it["HostIp"] as JsonString).string + + ":" + + (it["HostPort"] as JsonString).string + } + } else { + e.key + } + } + .toList() + app.names = name + if (running) { + app.uptime = + formatDuration( + ZonedDateTime.parse(startedAt), + OffsetDateTime.now(ZoneId.of("Z")).toZonedDateTime() + ) + } else { + app.uptime = "-" + } + app.signature = labels.getOrDefault("ids.signature", JsonValue.NULL).toString() + app.owner = labels.getOrDefault("ids.owner", JsonValue.NULL).toString() + app.description = + labels.getOrDefault("ids.description", JsonValue.NULL).toString() + app.labels = + labels + .entries + .stream() + .collect(Collectors.toMap({ it.key }, { it.value as Any })) + return@map app + } catch (e: IOException) { + LOG.error( + "Container iteration error occurred, skipping container with id " + + c.containerId(), + e + ) + return@map null } - app.signature = labels.getOrDefault("ids.signature", JsonValue.NULL).toString() - app.owner = labels.getOrDefault("ids.owner", JsonValue.NULL).toString() - app.description = labels.getOrDefault("ids.description", JsonValue.NULL).toString() - app.labels = labels.entries.stream() - .collect(Collectors.toMap({ it.key }, { it.value as Any })) - return@map app - } catch (e: IOException) { - LOG.error("Container iteration error occurred, skipping container with id " + c.containerId(), e) - return@map null } - }.filter { it != null }.map { it as ApplicationContainer }.collect(Collectors.toList()) + .filterNotNull() + .toList() } private fun getContainer(containerID: String): Container { - val filters = HashMap>() - filters["id"] = listOf(containerID) - val optionalContainer = getContainerStream(true, filters).findFirst() - if (optionalContainer.isEmpty) { - throw NoContainerExistsException("The container with ID $containerID has not been found!") - } else { - return optionalContainer.get() - } + return getContainerSequence(true, mapOf("id" to listOf(containerID))).firstOrNull() + ?: throw NoContainerExistsException( + "The container with ID $containerID has not been found!" + ) } + private fun getImage(container: Container) = + getImages(mapOf("reference" to listOf(container.getString("Image")))).firstOrNull() + override fun wipe(containerID: String) { val container = getContainer(containerID) try { LOG.info("Wiping containerID $containerID") container.remove(false, true, false) - val filters: MutableMap> = HashMap() - filters["reference"] = listOf(container.getString("Image")) - val optionalImage = getImageStream(filters).findFirst() - if (optionalImage.isEmpty) { - LOG.warn("The image to be deleted (filters: {}) was not found!", filters) - return + getImage(container)?.let { + LOG.info("Wiping image related to containerID $containerID") + it.delete() } - LOG.info("Wiping image related to containerID $containerID") - optionalImage.get().delete() + ?: run { + LOG.warn( + "The image to be deleted (filters: {}) was not found!", + mapOf("reference" to listOf(container.getString("Image"))) + ) + } } catch (e: Exception) { LOG.error(e.message, e) } @@ -278,11 +314,12 @@ class DockerCM : ContainerManager { // Instantly create a container from that image, but do not start it yet. LOG.info("Creating container instance from image {}", app.image) // Create the name - val containerName: String = if (app.name != null) { - app.name - } else { - defaultContainerName(app.image) - } + val containerName: String = + if (app.name != null) { + app.name + } else { + defaultContainerName(app.image) + } val container = Json.createObjectBuilder() val hostConfig = Json.createObjectBuilder() // Set image @@ -291,14 +328,19 @@ class DockerCM : ContainerManager { if (app.ports != null) { val exposedPorts = Json.createObjectBuilder() val portBindings = Json.createObjectBuilder() - val portRegex = ("(?:((?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}" + - "(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])):)?" + - "([0-9]+):([0-9]+)(?:/(tcp|udp))?").toRegex() + val portRegex = + ("(?:((?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}" + + "(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])):)?" + + "([0-9]+):([0-9]+)(?:/(tcp|udp))?") + .toRegex() for (port in app.ports) { val match = portRegex.matchEntire(port) if (match == null) { - LOG.warn("Port definition {} does not match the pattern " + - "[IPv4:]HostPort:ContainerPort[/tcp|udp], ignoring it", port) + LOG.warn( + "Port definition {} does not match the pattern " + + "[IPv4:]HostPort:ContainerPort[/tcp|udp], ignoring it", + port + ) } else { val groups = match.groupValues val protocol = (if (groups[4].isEmpty()) "tcp" else groups[4]) @@ -333,7 +375,9 @@ class DockerCM : ContainerManager { // Set restart policy if (app.restartPolicy != null) { hostConfig.add( - "RestartPolicy", Json.createObjectBuilder().add("Name", app.restartPolicy)) + "RestartPolicy", + Json.createObjectBuilder().add("Name", app.restartPolicy) + ) } // Set privileged state if (app.isPrivileged) { @@ -354,7 +398,6 @@ class DockerCM : ContainerManager { /** * Returns the default containerName that will be given to a container of image "imageID". * - * * For example, an imageID "shiva1029/weather" will be turned into "weather-shiva1029". * * @param imageName The name of the image @@ -376,19 +419,18 @@ class DockerCM : ContainerManager { * @param containerID The ID of the container to query labels from */ override fun getMetadata(containerID: String): Map { - val labels = HashMap() - getContainer(containerID).inspect().getJsonObject("Config").getJsonObject("Labels") - return labels + return getContainer(containerID).inspect().getJsonObject("Config").getJsonObject("Labels") } override fun setIpRule( - containerID: String, - direction: Direction, - srcPort: Int, - dstPort: Int, - srcDstRange: String, - protocol: Protocol, - decision: Decision) { // TODO Not implemented yet + containerID: String, + direction: Direction, + srcPort: Int, + dstPort: Int, + srcDstRange: String, + protocol: Protocol, + decision: Decision + ) { // TODO Not implemented yet } /** @@ -401,11 +443,9 @@ class DockerCM : ContainerManager { return getContainer(containerID).inspect().toString() } - /** - * Returns the version of docker on the system - */ + /** Returns the version of docker on the system */ override fun getVersion(): String { val version = DOCKER_CLIENT.version() return "${version.platformName()} (${version.version()})" } -} \ No newline at end of file +} diff --git a/ids-container-manager/src/test/java/de/fhg/aisec/ids/cm/impl/docker/DockerCmIT.java b/ids-container-manager/src/test/java/de/fhg/aisec/ids/cm/impl/docker/DockerCmIT.java deleted file mode 100644 index b82112778..000000000 --- a/ids-container-manager/src/test/java/de/fhg/aisec/ids/cm/impl/docker/DockerCmIT.java +++ /dev/null @@ -1,147 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-container-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.cm.impl.docker; - -import de.fhg.aisec.ids.api.cm.ApplicationContainer; -import de.fhg.aisec.ids.api.cm.ContainerStatus; -import org.junit.After; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import static org.junit.Assert.*; -import static org.junit.Assume.assumeTrue; - -public class DockerCmIT { - private List wipes = new ArrayList<>(); - - @After - public void cleanUp() { - // Remove containers created during test - DockerCM d = new DockerCM(); - wipes.forEach(d::wipe); - } - - @Test - public void testList() { - assumeTrue(DockerCM.Companion.isSupported()); - - DockerCM d = new DockerCM(); - - // List running containers - List lRunning = d.list(true); - assertNotNull(lRunning); - - // List all containers (also stopped ones) - List lAll = d.list(false); - assertNotNull(lAll); - - // we cannot have less running than total containers - assertTrue(lAll.size() >= lRunning.size()); - } - - @Test - public void testPull() { - assumeTrue(DockerCM.Companion.isSupported()); - - DockerCM d = new DockerCM(); - - // Pull the smallest possible image. Blocks. (must be online) - ApplicationContainer app = new ApplicationContainer(); - app.setImage("tianon/true"); - Optional oContainerID = d.pullImage(app); - - // We expect a new container to be created - assertTrue(oContainerID.isPresent()); - assertNotEquals("", oContainerID.get()); - wipes.add(oContainerID.get()); - - // we expect the container to be in list() - List containers = d.list(false); - Optional container = - containers.stream().filter(c -> c.getId().equals(oContainerID.get())).findAny(); - assertTrue(container.isPresent()); - - assertEquals(ContainerStatus.CREATED, container.get().getStatus()); - } - - @Test - public void testVersion() { - assumeTrue(DockerCM.Companion.isSupported()); - - DockerCM d = new DockerCM(); - - var version = d.getVersion(); - assertFalse(version.isEmpty()); - var regex = ".* \\([0-9.]+(?:-.+)?\\)"; - if (!version.matches(regex)) { - throw new AssertionError( - "Error: Docker version has to match regex '" + regex + "', found '" + version + "'"); - } - } - - @Test - public void testStartStop() { - assumeTrue(DockerCM.Companion.isSupported()); - - DockerCM d = new DockerCM(); - - // Pull an image we can actually start. (must be online) - ApplicationContainer app = new ApplicationContainer(); - app.setImage("nginx"); - Optional oContainerID = d.pullImage(app); - - // We expect a new container to be created - assertTrue(oContainerID.isPresent()); - String containerID = oContainerID.get(); - wipes.add(containerID); - assertNotNull(containerID); - - // we expect the container to be in list() - List containers = d.list(false); - Optional container = - containers.stream().filter(c -> c.getId().equals(containerID)).findAny(); - assertTrue(container.isPresent()); - - assertEquals(ContainerStatus.CREATED, container.get().getStatus()); - - // Start container - d.startContainer(containerID, null); - - // We now expect it in list of running containers - containers = d.list(true); - Optional runningContainer = - containers.stream().filter(c -> c.getId().equals(containerID)).findAny(); - assertTrue(runningContainer.isPresent()); - assertEquals(ContainerStatus.RUNNING, runningContainer.get().getStatus()); - - // Stop container - d.stopContainer(containerID); - - // We expect it to be still in list of all containers - containers = d.list(false); - Optional stoppedContainer = - containers.stream().filter(c -> c.getId().equals(containerID)).findAny(); - assertTrue(stoppedContainer.isPresent()); - assertEquals(ContainerStatus.EXITED, stoppedContainer.get().getStatus()); - } -} diff --git a/ids-container-manager/src/test/kotlin/de/fhg/aisec/ids/cm/impl/docker/DockerCmIT.kt b/ids-container-manager/src/test/kotlin/de/fhg/aisec/ids/cm/impl/docker/DockerCmIT.kt new file mode 100644 index 000000000..aecaa6f5d --- /dev/null +++ b/ids-container-manager/src/test/kotlin/de/fhg/aisec/ids/cm/impl/docker/DockerCmIT.kt @@ -0,0 +1,128 @@ +/*- + * ========================LICENSE_START================================= + * ids-container-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.cm.impl.docker + +import de.fhg.aisec.ids.api.cm.ApplicationContainer +import de.fhg.aisec.ids.api.cm.ContainerStatus +import de.fhg.aisec.ids.cm.impl.docker.DockerCM.Companion.isSupported +import java.util.* +import org.junit.After +import org.junit.Assert +import org.junit.Assume +import org.junit.Test + +class DockerCmIT { + private val wipes: MutableSet = HashSet() + @After + fun cleanUp() { + // Remove containers created during test + DockerCM().let { d -> wipes.forEach { d.wipe(it) } } + } + + @Test + fun testList() { + Assume.assumeTrue(isSupported) + val d = DockerCM() + + // List running containers + val lRunning = d.list(true) + Assert.assertNotNull(lRunning) + + // List all containers (also stopped ones) + val lAll = d.list(false) + Assert.assertNotNull(lAll) + + // we cannot have less running than total containers + Assert.assertTrue(lAll.size >= lRunning.size) + } + + @Test + fun testPull() { + Assume.assumeTrue(isSupported) + val d = DockerCM() + + // Pull the smallest possible image. Blocks. (must be online) + val app = ApplicationContainer() + app.image = "tianon/true" + val oContainerID = d.pullImage(app) + + // We expect a new container to be created + Assert.assertTrue(oContainerID.isPresent) + Assert.assertNotEquals("", oContainerID.get()) + wipes.add(oContainerID.get()) + + // we expect the container to be in list() + val container = d.list(false).firstOrNull { it.id == oContainerID.get() } + Assert.assertNotNull(container) + Assert.assertEquals(ContainerStatus.CREATED, container?.status) + } + + @Test + fun testVersion() { + Assume.assumeTrue(isSupported) + val d = DockerCM() + val version = d.version + Assert.assertFalse(version.isEmpty()) + val regex = Regex(".* \\([0-9.]+(?:.+)?\\)") + if (!version.matches(regex)) { + throw AssertionError( + "Error: Docker version has to match regex '$regex', found '$version'" + ) + } + } + + @Test + fun testStartStop() { + Assume.assumeTrue(isSupported) + val d = DockerCM() + + // Pull an image we can actually start. (must be online) + val app = ApplicationContainer() + app.image = "nginx" + val oContainerID = d.pullImage(app) + + // We expect a new container to be created + Assert.assertTrue(oContainerID.isPresent) + val containerID = oContainerID.get() + wipes.add(containerID) + Assert.assertNotNull(containerID) + + // we expect the container to be in list() + val container = d.list(false).firstOrNull { it.id == containerID } + Assert.assertNotNull(container) + Assert.assertEquals(ContainerStatus.CREATED, container?.status) + + // Start container + d.startContainer(containerID, null) + + // We now expect it in list of running containers + val runningContainer = d.list(true).firstOrNull { it.id == containerID } + Assert.assertNotNull(runningContainer) + Assert.assertEquals(ContainerStatus.RUNNING, runningContainer?.status) + + // Stop container + d.stopContainer(containerID) + + // We expect it to be still in list of all containers + val stoppedContainer = d.list(false).firstOrNull { it.id == containerID } + Assert.assertNotNull(stoppedContainer) + Assert.assertEquals(ContainerStatus.EXITED, stoppedContainer?.status) + } +} diff --git a/ids-dataflow-control/bnd.bnd b/ids-dataflow-control/bnd.bnd index 8d1b54897..364cacf6a 100644 --- a/ids-dataflow-control/bnd.bnd +++ b/ids-dataflow-control/bnd.bnd @@ -1,6 +1,7 @@ Bundle-Name: IDS :: Dataflow Control Engine Export-Package: \ + alice*;-split-package:=merge-last,\ de.fhg.aisec.ids.dataflowcontrol* Import-Package: \ - !org.checkerframework.checker*,\ - * + !dalvik*,\ + * diff --git a/ids-dataflow-control/build.gradle b/ids-dataflow-control/build.gradle deleted file mode 100644 index e9dd0e39d..000000000 --- a/ids-dataflow-control/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - - providedByBundle(group: 'com.google.guava', name: 'guava', version: libraryVersions.guava) { - transitive = false // Avoid pulling in of checker framework and other annotation stuff - } - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - providedByBundle group: 'it.unibo.alice.tuprolog', name: 'tuprolog', version: libraryVersions.tuprolog - - compileOnly group: 'org.checkerframework', name: 'checker-qual', version: libraryVersions.checkerQual - - osgiCore group: 'org.osgi', name: 'osgi.cmpn', version: libraryVersions.osgiCompendium - - testImplementation group: 'junit', name: 'junit', version: libraryVersions.junit4 - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito -} diff --git a/ids-dataflow-control/build.gradle.kts b/ids-dataflow-control/build.gradle.kts new file mode 100644 index 000000000..610ecd901 --- /dev/null +++ b/ids-dataflow-control/build.gradle.kts @@ -0,0 +1,22 @@ +description = "Camel IDS Component" + +dependencies { + @Suppress("UNCHECKED_CAST") val libraryVersions = + rootProject.extra.get("libraryVersions") as Map + + providedByBundle(project(":ids-api")) { isTransitive = false } + + providedByBundle("com.google.guava", "guava", libraryVersions["guava"]) + + implementation("it.unibo.alice.tuprolog", "2p-core", libraryVersions["2p"]) + implementation("it.unibo.alice.tuprolog", "2p-parser", libraryVersions["2p"]) +// implementation("it.unibo.alice.tuprolog", "2p-presentation", libraryVersions["2p"]) + providedByBundle("org.apache.commons", "commons-text", libraryVersions["commonsText"]) + providedByBundle("com.codepoetics", "protonpack", libraryVersions["protonpack"]) + providedByBundle("org.antlr", "antlr4-runtime", libraryVersions["antlr4"]) + + osgiCore("org.osgi", "osgi.cmpn", libraryVersions["osgiCompendium"]) + + testImplementation("junit", "junit", libraryVersions["junit4"]) + testImplementation("org.mockito", "mockito-core", libraryVersions["mockito"]) +} diff --git a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/CounterExampleImpl.java b/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/CounterExampleImpl.java deleted file mode 100644 index e32741915..000000000 --- a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/CounterExampleImpl.java +++ /dev/null @@ -1,92 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-dataflow-control - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.dataflowcontrol.lucon; - -import alice.tuprolog.Struct; -import alice.tuprolog.Term; -import de.fhg.aisec.ids.api.router.CounterExample; -import java.util.Iterator; -import java.util.LinkedList; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -public class CounterExampleImpl extends CounterExample { - - public CounterExampleImpl(@NonNull Term term) { - Iterator traceIterator = ((Struct) term).listIterator(); - LinkedList steps = new LinkedList<>(); - // process explanation - Iterator reasonIterator = ((Struct) traceIterator.next()).listIterator(); - StringBuilder sb = - new StringBuilder() - .append("Service ") - .append(reasonIterator.next().toString()) - .append(" may receive messages"); - reasonIterator.next(); - // Term explanation = reasonIterator.next(); - //// if (explanation.isList()) { - // sb.append(" labeled ["); - // appendCSList(sb, explanation); - // sb.append("]"); - //// } - sb.append(", which is forbidden by rule \"") - .append(reasonIterator.next().toString()) - .append("\"."); - this.setExplanation(sb.toString()); - // process steps and prepend them to list (inverse trace to get the right order) - traceIterator.forEachRemaining(t -> steps.addFirst(termToStep(t))); - this.setSteps(steps); - } - - @Nullable - public static String termToStep(@Nullable Term t) { - if (t == null) { - return null; - } - Struct traceEntry = (Struct) t; - StringBuilder sb = new StringBuilder(); - // node name is the head of the list - String node = traceEntry.listHead().toString(); - sb.append(node); - // the label list is the new head of the remaining list (tail) - Term labelList = traceEntry.listTail().listHead(); - if (!labelList.isEmptyList()) { - sb.append(" receives message labelled "); - appendCSList(sb, labelList); - return sb.toString(); - } else { - return sb.append(" receives message without labels").toString(); - } - } - - public static void appendCSList(@Nullable StringBuilder sb, @Nullable Term l) { - if (sb == null || l == null) { - return; - } - - if (l.isList() && !l.isEmptyList()) { - Iterator listIterator = ((Struct) l).listIterator(); - // add first element - sb.append(listIterator.next().toString()); - // add remaining elements - listIterator.forEachRemaining(lt -> sb.append(", ").append(lt.toString())); - } - } -} diff --git a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconLibrary.java b/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconLibrary.java deleted file mode 100644 index 711eefdb7..000000000 --- a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconLibrary.java +++ /dev/null @@ -1,210 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-dataflow-control - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.dataflowcontrol.lucon; - -import alice.tuprolog.Library; -import alice.tuprolog.Number; -import alice.tuprolog.Term; -import alice.tuprolog.Var; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Plugins and default theories for tuProlog engine. - * - * @author Michael Lux (michael.lux@aisec.fraunhofer.de) - */ -public class LuconLibrary extends Library { - private static final long serialVersionUID = 1L; - private static final Logger LOG = LoggerFactory.getLogger(LuconLibrary.class); - - private transient LoadingCache regexCache = - CacheBuilder.newBuilder() - .expireAfterAccess(1, TimeUnit.DAYS) - .maximumWeight((long) 1e6) - .weigher((k, v) -> ((String) k).length()) - .build( - new CacheLoader() { - public Pattern load(String key) { - return Pattern.compile(key); - } - }); - - @Override - public String getTheory() { - return "set_of(In, Out) :- % get a pairwise different, sorted set from a list\n" - + " quicksort(In, '@<', Sorted),\n" - + " no_duplicates(Sorted, Out).\n" - + "\n" - + "get_labels(Out) :- % collect and return asserted labels\n" - + " once(setof(L, label(L), Out) ; Out = []).\n" - + "\n" - + "assert_labels(L, A) :- assert_labels(L, A, []).\n" - + "assert_labels([], A, A).\n" - + "assert_labels([L|Tail], Ar, A) :- label(L), assert_labels(Tail, Ar, A), !.\n" - + "assert_labels([L|Tail], Ar, A) :- assert(label(L)), assert_labels(Tail, Ar, [L|A]).\n" - + "\n" - + "retract_labels(L, R) :- retract_labels(L, R, []).\n" - + "retract_labels([], R, R).\n" - + "retract_labels([L|Tail], Rr, R) :- retract(label(L)), retract_labels(Tail, Rr, [L|R]), !.\n" - + "retract_labels([L|Tail], Rr, R) :- retract_labels(Tail, Rr, R).\n" - + "\n" - + "all_ground([]).\n" - + "all_ground([Head|Tail]) :- ground(Head), all_ground(Tail).\n" - + "\n" - + "cache_put_all_unsafe(KL, []).\n" - + "cache_put_all_unsafe(KL, [V|T]) :- cache_put_unsafe(KL, V), cache_put_all_unsafe(KL, T).\n" - + "cache_put_unsafe(KL, V) :-\n" - + " %print([\"CACHE PUT: \"|[KL, V]]), nl,\n" - + " assertz(cache_entry(KL, V)).\n" - + "\n" - + "cache_put_all(KL, VL) :- all_ground(KL), cache_put_all_unsafe(KL, VL).\n" - + "cache_put(KL, V) :- cache_put_check(KL, V); true.\n" - + "cache_put_check(KL, V) :- all_ground(KL), cache_put_unsafe(KL, V).\n" - + "\n" - + "cache_get(KL, V) :-\n" - + " cache_entry(KL, V).\n" - + " %-> print([\"CACHE HIT: \", KL, V]), nl\n" - + " %; print([\"CACHE MISS: \", KL]), nl, fail.\n" - + "\n" - + "cache_clear(KL) :- retractall(cache_entry(KL, _)).\n" - + "\n" - + "action_service(Action, S) :- % Finds services S matching endpoints of N [ O(|Ep_S|) ]\n" - + " has_endpoint(S, Regex), % a service S exists such that [ O(|Ep_S|) ]\n" - + " regex_match(Regex, Action). % the action of A matches the endpoint of S [ assume O(1) ]\n" - + "\n" - + "collect_creates_labels([], []).\n" - + "collect_creates_labels([S|SCTail], ACout) :-\n" - + " collect_creates_labels(SCTail, ACnew),\n" - + " findall(A, creates_label(S, A), AC),\n" - + " once(bound(ACnew); ACnew = []),\n" - + " append(AC, ACnew, ACout).\n" - + "\n" - + "collect_removes_labels([], []).\n" - + "collect_removes_labels([S|SCTail], RCout) :-\n" - + " collect_removes_labels(SCTail, RCnew),\n" - + " findall(R, removes_label(S, R), RC),\n" - + " once(bound(RCnew); RCnew = []),\n" - + " append(RC, RCnew, RCout).\n" - + "\n" - + "update_labels(Act, Out, Aout, Rout) :- % Updates labels according to spec. of service S\n" - + " once(setof(S, action_service(Act, S), SC); SC = []), % collect all relevant services\n" - + " collect_creates_labels(SC, ACraw), set_of(ACraw, AC), assert_labels(AC, Aout), % assert new labels added by S\n" - + " collect_removes_labels(SC, RCraw), set_of(RCraw, RC), retract_labels(RC, Rout), % retract labels removed by S\n" - + " %print([Act, \"=>\", SC, \"added:\", Aout, \"removed:\", Rout]),nl,\n" - + " get_labels(Out). % collect and return asserted labels\n" - + "\n" - + "dominant_rules(Act, Req, DC, S, R) :- % Find the dominant rule R for action Act (from cache)\n" - + " get_labels(LC), % Collect currently asserted labels\n" - + " cache_get([dr, Act, Req, DC, LC], V), % CACHE GET entry\n" - + " list(V), V = [S, R]. % unpack result\n" - + "\n" - + "dominant_rules(Act, Req, DC, S, R) :- % Find the dominant rule R for action Act [ O(|Ep_S| x |S -- R|) ]\n" - + " get_labels(LC), % Collect currently asserted labels\n" - + " \\+(cache_get([dr, Act, Req, DC, LC], V)), % CACHE GET entry\n" - + " (setof(DomRule, (\n" - + " action_service(Act, Si), % Action Act is matched by a service Si [ O(|Ep_S|) ]\n" - + " rule(Ri), receives_label(Ri), % There is a VALID rule Ri\n" - + " has_target(Ri, Si), % targeting by service Si [ O(|S -- R|) ]\n" - + " has_decision(Ri, Req), % with a decision that unifies with Require [ O(1) ]\n" - + " rule_priority(Ri, PR), % that has priority PR, then [ O(1) ]\n" - + " \\+( % there MUST NOT exist [ O(|Ep_S| x |S -- R|) ]\n" - + " action_service(Act, S2), % a service S2 [ O(|Ep_S|) ]\n" - + " rule(R2), Ri \\= R2, receives_label(R2), % with another VALID rule R2\n" - + " has_target(R2, S2), % that is targeting S2 [ O(|S -- R|) ]\n" - + " has_decision(R2, D2), D2 \\= Req, % which enforces a different decision, [ O(1) ]\n" - + " rule_priority(R2, PR2), % and has priority PR2 [ O(1) ]\n" - + " G =.. [DC, PR2, PR], call(G) % such that 'DC'(PR, PR2) is fulfilled [ O(1) ]\n" - + " ), DomRule = [Si, Ri] % compose the result\n" - + " ), RL)\n" - + " -> cache_put_all([dr, Act, Req, DC, LC], RL) % IF successful, CACHE PUT ALL results\n" - + " ; cache_put([dr, Act, Req, DC, LC], none) % ELSE CACHE PUT 'none'\n" - + " ), !, % don't backtrack into the caching logic\n" - + " dominant_rules(Act, Req, DC, S, R). % delegate to cache handler\n" - + "\n" - + "dominant_drop_rules(Act, S, R) :- dominant_rules(Act, drop, '>', S, R).\n" - + "dominant_allow_rules(Act, S, R) :- dominant_rules(Act, allow, '>=', S, R).\n" - + "\n" - + "% Query for a path between two nodes and print the labels along the possible paths like so:\n" - + "%\n" - + "% path(stmt_1, stmt_5, Trace).\n" - + "%\n" - + "path(A,B,T) :- % Two nodes are connected if we can walk from A to B,\n" - + " trace_walk(A, B, [], [[A, []]], T). % starting with empty label list\n" - + "\n" - + "trace_walk(A, B, L, Log, T) :- % We have walked from A to B and verify [ O(|Ep_S| x |S -- R|) ]\n" - + " A = B, % A is the desired destination with [ O(1) ]\n" - + " has_action(A, Act), % an action Act and there is [ O(1) ]\n" - + " dominant_drop_rules(Act, S, R), % a dominant drop rule R and service S for Act [ O(|Ep_S| x |S -- R|) ]\n" - + " receives_label(R), % R receives a set of labels with [ assume O(1) ]\n" - + " get_labels(LC), % get asserted labels [ O(L_a), assume O(1) ]\n" - + " T = [[S, LC, R]|Log]. % [unify the recursion result with Out] [ O(1) ]\n" - + " %print(\"finished (END): \"), print(A), nl.\n" - + "\n" - + "trace_walk(A, B, L, Log, T) :- % We can walk from A to B if [ O(|Ep_S| x |S -- R|) ]\n" - + " succ(A, X), % A is connected to X and there is [ O(|succ(A, _)|), assume O(1) ]\n" - + " has_action(A, Act), % an action Action and there is [ O(1) ]\n" - + " dominant_allow_rules(Act, S, _), % a dominant allow rule and service S for Act [ O(|Ep_S| x |S -- R|) ]\n" - + " update_labels(Act, LN, Aout, Rout), % [update the labels for the next step] [ O(|L|), assume O(1) ],\n" - + " %print([Aout, Rout]), nl,\n" - + " %print(\"transition: \"), print([A, X, S, LN]), nl,\n" - + " (\n" - + " trace_walk(X, B, LN, [[X, LN]|Log], T) % we can get from X to B [ Recursion! ]\n" - + " ; true % or otherwise, make sure that the cleanup stuff below gets called!\n" - + " ),\n" - + " retract_labels(Aout, _), % retract labels asserted before recursion\n" - + " assert_labels(Rout, _), % assert labels retracted before recursion\n" - + " %print(\"finished: \"), print(A), nl,\n" - + " ground(T). % If T is bound, recursion returned successfully, no result otherwise!\n"; - } - - private static boolean isComplex(@NonNull Term t) { - if (t instanceof Var) { - t = t.getTerm(); - } - return (!t.isAtom() || t.isList()) && !(t instanceof Number); - } - - @SuppressWarnings("unused") - public boolean regex_match_2(Term regex, Term input) { - LOG.trace("regex_match/2 called with " + regex + " " + input); - // Both regex and input string must be ground - if (isComplex(regex) || isComplex(input)) { - return false; - } - try { - String regexString = TuPrologHelper.unquote(regex.getTerm().toString()); - String inputString = TuPrologHelper.unquote(input.getTerm().toString()); - boolean match = regexCache.get(regexString).matcher(inputString).matches(); - LOG.trace("regex_match: " + regexString + " , " + inputString + ": " + match); - return match; - } catch (ExecutionException e) { - LOG.warn(e.getMessage(), e); - return false; - } - } -} diff --git a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/TuPrologHelper.java b/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/TuPrologHelper.java deleted file mode 100644 index 9afc2ff82..000000000 --- a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/TuPrologHelper.java +++ /dev/null @@ -1,80 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-dataflow-control - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.dataflowcontrol.lucon; - -import alice.tuprolog.Prolog; -import alice.tuprolog.Struct; -import alice.tuprolog.Term; -import java.util.Iterator; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -public final class TuPrologHelper { - - private static final ThreadLocal threadProlog = ThreadLocal.withInitial(Prolog::new); - - public static Prolog getVm() { - return threadProlog.get(); - } - - @NonNull - public static String escape(@Nullable String s) { - if (s == null) { - return ""; - } - StringBuilder sb = new StringBuilder(); - sb.append('\''); - int charLength = s.length(); - for (int i = 0; i < charLength; i++) { - char c = s.charAt(i); - sb.append(c == '\'' ? "''" : c); - } - sb.append('\''); - return sb.toString(); - } - - @NonNull - public static Stream listStream(@Nullable Term list) { - if (list == null) { - return Stream.empty(); - } - if (!list.isList()) { - throw new IllegalArgumentException("Not a tuProlog list"); - } - Iterator listIterator = ((Struct) list).listIterator(); - return StreamSupport.stream( - Spliterators.spliteratorUnknownSize(listIterator, Spliterator.ORDERED), false); - } - - @NonNull - static String unquote(@NonNull String s) { - if (s.length() > 2 && s.charAt(0) == '\'' && s.charAt(s.length() - 1) == '\'') { - return s.substring(1, s.length() - 1); - } else if (s.length() == 2 && "''".equals(s)) { - return ""; - } else { - return s; - } - } -} diff --git a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/PolicyDecisionPoint.kt b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/PolicyDecisionPoint.kt similarity index 81% rename from ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/PolicyDecisionPoint.kt rename to ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/PolicyDecisionPoint.kt index c3b7a2d0d..9b37ec292 100644 --- a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/PolicyDecisionPoint.kt +++ b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/PolicyDecisionPoint.kt @@ -19,7 +19,12 @@ */ package de.fhg.aisec.ids.dataflowcontrol -import alice.tuprolog.* +import alice.tuprolog.SolveInfo +import alice.tuprolog.Var +import alice.tuprolog.exceptions.MalformedGoalException +import alice.tuprolog.exceptions.NoMoreSolutionException +import alice.tuprolog.exceptions.NoSolutionException +import alice.tuprolog.exceptions.PrologException import com.google.common.cache.CacheBuilder import de.fhg.aisec.ids.api.policy.* import de.fhg.aisec.ids.api.policy.PolicyDecision.Decision @@ -28,13 +33,13 @@ import de.fhg.aisec.ids.api.router.RouteVerificationProof import de.fhg.aisec.ids.dataflowcontrol.lucon.LuconEngine import de.fhg.aisec.ids.dataflowcontrol.lucon.TuPrologHelper.escape import de.fhg.aisec.ids.dataflowcontrol.lucon.TuPrologHelper.listStream -import org.osgi.service.component.ComponentContext -import org.osgi.service.component.annotations.* -import org.slf4j.LoggerFactory import java.io.File import java.util.* import java.util.concurrent.ExecutionException import java.util.concurrent.TimeUnit +import org.osgi.service.component.ComponentContext +import org.osgi.service.component.annotations.* +import org.slf4j.LoggerFactory /** * servicefactory=false is the default and actually not required. But we want to make clear that @@ -54,7 +59,8 @@ class PolicyDecisionPoint : PDP, PAP { @Volatile private var routeManager: RouteManager? = null - private val transformationCache = CacheBuilder.newBuilder() + private val transformationCache = + CacheBuilder.newBuilder() .maximumSize(10000) .expireAfterAccess(1, TimeUnit.DAYS) .build() @@ -63,32 +69,31 @@ class PolicyDecisionPoint : PDP, PAP { * Creates a query to retrieve policy decision from Prolog knowledge base. * * @param target The target node of the transformation - * @param properties The exchange properties + * @param labels The exchange properties */ - private fun createDecisionQuery( - target: ServiceNode, properties: MutableMap): String { + private fun createDecisionQuery(target: ServiceNode, labels: Set): String { val sb = StringBuilder() sb.append("rule(X), has_target(X, T), ") sb.append("has_endpoint(T, EP), ") sb.append("regex_match(EP, ").append(escape(target.endpoint)).append("), ") // Assert labels for the duration of this query, must be done before receives_label(X) - @Suppress("UNCHECKED_CAST") - val labels = properties.computeIfAbsent(PDP.LABELS_KEY) { HashSet() } as Set labels.forEach { k -> sb.append("assert(label(").append(k).append(")), ") } sb.append("receives_label(X), ") sb.append("rule_priority(X, P), ") // Removed due to unclear relevance -// if (target.capabilties.size + target.properties.size > 0) { -// val capProp = LinkedList() -// for (cap in target.capabilties) { -// capProp.add("has_capability(T, " + escape(cap) + ")") -// } -// for (prop in target.properties) { -// capProp.add("has_property(T, " + escape(prop) + ")") -// } -// sb.append("(").append(capProp.joinToString(", ")).append("), ") -// } - sb.append("(has_decision(X, D) ; (has_obligation(X, _O), has_alternativedecision(_O, Alt), ") + // if (target.capabilties.size + target.properties.size > 0) { + // val capProp = LinkedList() + // for (cap in target.capabilties) { + // capProp.add("has_capability(T, " + escape(cap) + ")") + // } + // for (prop in target.properties) { + // capProp.add("has_property(T, " + escape(prop) + ")") + // } + // sb.append("(").append(capProp.joinToString(", ")).append("), ") + // } + sb.append( + "(has_decision(X, D) ; (has_obligation(X, _O), has_alternativedecision(_O, Alt), " + ) sb.append("requires_prerequisite(_O, A)))") if (labels.isNotEmpty()) { // Cleanup prolog VM for next run @@ -102,7 +107,6 @@ class PolicyDecisionPoint : PDP, PAP { * A transformation query retrieves the set of labels to add and to remove from the Prolog * knowledge base. * - * * This method returns the respective query for a specific target. * * @param target The ServiceNode to be processed @@ -113,26 +117,26 @@ class PolicyDecisionPoint : PDP, PAP { val plEndpoint: String if (target.endpoint != null) { plEndpoint = escape(target.endpoint) -// sb.append("dominant_allow_rules(").append(plEndpoint).append(", _T, _), ") + // sb.append("dominant_allow_rules(").append(plEndpoint).append(", _T, _), ") } else { throw RuntimeException("No endpoint specified!") } // Removed due to unclear relevance -// if (target.capabilties.size + target.properties.size > 0) { -// val capProp = LinkedList() -// for (cap in target.capabilties) { -// capProp.add("has_capability(_T, " + escape(cap) + ")") -// } -// for (prop in target.properties) { -// capProp.add("has_property(_T, " + escape(prop) + ")") -// } -// sb.append('(').append(capProp.joinToString(", ")).append("),\n") -// } + // if (target.capabilties.size + target.properties.size > 0) { + // val capProp = LinkedList() + // for (cap in target.capabilties) { + // capProp.add("has_capability(_T, " + escape(cap) + ")") + // } + // for (prop in target.properties) { + // capProp.add("has_property(_T, " + escape(prop) + ")") + // } + // sb.append('(').append(capProp.joinToString(", ")).append("),\n") + // } sb.append("once(setof(S, action_service(") - .append(plEndpoint) - .append(", S), SC); SC = []),\n") - .append("collect_creates_labels(SC, ACraw), set_of(ACraw, Adds),\n") - .append("collect_removes_labels(SC, RCraw), set_of(RCraw, Removes).") + .append(plEndpoint) + .append(", S), SC); SC = []),\n") + .append("collect_creates_labels(SC, ACraw), set_of(ACraw, Adds),\n") + .append("collect_removes_labels(SC, RCraw), set_of(RCraw, Removes).") return sb.toString() } @@ -167,9 +171,7 @@ class PolicyDecisionPoint : PDP, PAP { override fun requestTranformations(lastServiceNode: ServiceNode): TransformationDecision { try { - return transformationCache.get( - lastServiceNode - ) { + return transformationCache.get(lastServiceNode) { // Query prolog for labels to remove or add from message val query = this.createTransformationQuery(lastServiceNode) if (LOG.isDebugEnabled) { @@ -193,7 +195,9 @@ class PolicyDecisionPoint : PDP, PAP { } val removes = s.getVarValue("Removes").term if (removes.isList) { - listStream(removes).forEach { labelsToRemove.add(it.toString()) } + listStream(removes).forEach { + labelsToRemove.add(it.toString()) + } } else { throw RuntimeException("\"Removes\" is not a prolog list!") } @@ -211,26 +215,25 @@ class PolicyDecisionPoint : PDP, PAP { LOG.error(ee.message, ee) return TransformationDecision() } - } override fun requestDecision(req: DecisionRequest): PolicyDecision { val dec = PolicyDecision() - - LOG.debug( - "Decision requested " + req.from.endpoint + " -> " + req.to.endpoint) + if (LOG.isTraceEnabled) { + LOG.trace("Decision requested " + req.from.endpoint + " -> " + req.to.endpoint) + } try { // Query Prolog engine for a policy decision val startTime = System.nanoTime() - val query = this.createDecisionQuery(req.to, req.properties) - if (LOG.isDebugEnabled) { - LOG.debug("Decision query: {}", query) + val query = this.createDecisionQuery(req.to, req.labels) + if (LOG.isTraceEnabled) { + LOG.trace("Decision query: {}", query) } val solveInfo = this.engine.query(query, true) val time = System.nanoTime() - startTime - if (LOG.isInfoEnabled) { - LOG.debug("Decision query took {} ms", time / 1e6f) + if (LOG.isTraceEnabled) { + LOG.trace("Decision query took {} ms", time / 1e6f) } // If there is no matching rule, deny by default @@ -260,7 +263,6 @@ class PolicyDecisionPoint : PDP, PAP { } catch (e: NullPointerException) { LOG.warn("Invalid rule priority: " + si.getVarValue("P"), e) } - } // Just for debugging @@ -331,16 +333,21 @@ class PolicyDecisionPoint : PDP, PAP { for (i in solveInfo) { if (i.isSuccess) { val vars = i.bindingVars - LOG.trace(vars.joinToString(", ") { v -> - String.format("%s: %s (%s)", v.name, v.term, - if (v.isBound) "bound" else "unbound") - }) + LOG.trace( + vars.joinToString(", ") { v -> + String.format( + "%s: %s (%s)", + v.name, + v.term, + if (v.isBound) "bound" else "unbound" + ) + } + ) } } } catch (nse: NoSolutionException) { LOG.trace("No solution found", nse) } - } override fun clearAllCaches() { @@ -393,6 +400,7 @@ class PolicyDecisionPoint : PDP, PAP { private const val LUCON_FILE_EXTENSION = ".pl" // Each thread creates a LuconEngine instance to prevent concurrency issues - val threadEngine: ThreadLocal = ThreadLocal.withInitial { LuconEngine(System.out) } + val threadEngine: ThreadLocal = + ThreadLocal.withInitial { LuconEngine(System.out) } } } diff --git a/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/CounterExampleImpl.kt b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/CounterExampleImpl.kt new file mode 100644 index 000000000..9e9ad6edc --- /dev/null +++ b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/CounterExampleImpl.kt @@ -0,0 +1,89 @@ +/*- + * ========================LICENSE_START================================= + * ids-dataflow-control + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.dataflowcontrol.lucon + +import alice.tuprolog.Struct +import alice.tuprolog.Term +import de.fhg.aisec.ids.api.router.CounterExample +import java.util.* + +class CounterExampleImpl(term: Term) : CounterExample() { + + init { + val traceIterator = (term as Struct).listIterator() + val steps = LinkedList() + // process explanation + val reasonIterator = (traceIterator.next() as Struct).listIterator() + val sb = + StringBuilder() + .append("Service ") + .append(reasonIterator.next().toString()) + .append(" may receive messages") + reasonIterator.next() + // val explanation = reasonIterator.next() + // if (explanation.isList) { + // sb.append(" labeled [") + // appendCSList(sb, explanation) + // sb.append("]") + // } + sb.append(", which is forbidden by rule \"") + .append(reasonIterator.next().toString()) + .append("\".") + this.explanation = sb.toString() + // process steps and prepend them to list (inverse trace to get the right order) + traceIterator.forEachRemaining { t: Term? -> steps.addFirst(termToStep(t)) } + this.steps = steps + } + + companion object { + fun termToStep(t: Term?): String? { + if (t == null) { + return null + } + val traceEntry = t as Struct + val sb = StringBuilder() + // node name is the head of the list + val node = traceEntry.listHead().toString() + sb.append(node) + // the label list is the new head of the remaining list (tail) + val labelList = traceEntry.listTail().listHead() + return if (!labelList.isEmptyList) { + sb.append(" receives message labelled ") + appendCSList(sb, labelList) + sb.toString() + } else { + sb.append(" receives message without labels").toString() + } + } + + private fun appendCSList(sb: StringBuilder?, l: Term?) { + if (sb == null || l == null) { + return + } + if (l.isList && !l.isEmptyList) { + val listIterator = (l as Struct).listIterator() + // add first element + sb.append(listIterator.next().toString()) + // add remaining elements + listIterator.forEachRemaining { lt: Term -> sb.append(", ").append(lt.toString()) } + } + } + } +} diff --git a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconEngine.kt b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconEngine.kt similarity index 87% rename from ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconEngine.kt rename to ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconEngine.kt index 3c6a6835a..d46cbdaf6 100644 --- a/ids-dataflow-control/src/main/java/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconEngine.kt +++ b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconEngine.kt @@ -19,23 +19,27 @@ */ package de.fhg.aisec.ids.dataflowcontrol.lucon -import alice.tuprolog.* +import alice.tuprolog.Prolog +import alice.tuprolog.SolveInfo +import alice.tuprolog.Theory import alice.tuprolog.event.LibraryEvent -import alice.tuprolog.event.LibraryListener +import alice.tuprolog.exceptions.InvalidLibraryException +import alice.tuprolog.exceptions.InvalidTheoryException +import alice.tuprolog.exceptions.MalformedGoalException +import alice.tuprolog.exceptions.NoSolutionException +import alice.tuprolog.interfaces.event.LibraryListener import de.fhg.aisec.ids.api.router.CounterExample import de.fhg.aisec.ids.api.router.RouteVerificationProof -import org.slf4j.LoggerFactory import java.io.OutputStream import java.nio.charset.StandardCharsets import java.util.* import java.util.regex.Pattern +import org.slf4j.LoggerFactory /** * LUCON (Logic based Usage Control) policy decision engine. * - * - * This engine uses tuProlog as a logic language implementation to answer policy decision - * requests. + * This engine uses tuProlog as a logic language implementation to answer policy decision requests. * * @author Julian Schuette (julian.schuette@aisec.fraunhofer.de) */ @@ -43,8 +47,7 @@ class LuconEngine /** * Create a new LuconEngine which writes to a given output stream. * - * @param out OutputStream to write Prolog engine outputs to, or null if output should not - * printed. + * @param out OutputStream to write Prolog engine outputs to, or null if output should not printed. */ (out: OutputStream?) { private val p: Prolog = Prolog() @@ -55,23 +58,20 @@ class LuconEngine return t?.toString() ?: "" } - val theoryAsJSON: String - get() { - val t = p.theory - return if (t == null) "" else t.toJSON() - } - init { try { - p.theory = Theory(defaultPolicy) + p.theory = Theory.parseWithStandardOperators(defaultPolicy) } catch (e: Exception) { LOG.error("Error loading default policy", e) } // Add some listeners for logging/debugging p.addExceptionListener { ex -> LOG.error("Exception in Prolog reasoning: " + ex.msg) } - p.addQueryListener { q -> LOG.trace("Prolog query " + q.solveInfo.query.toString()) } - p.addLibraryListener( + if (LOG.isTraceEnabled) { + p.addQueryListener { q -> LOG.trace("Prolog query " + q.solveInfo.query.toString()) } + } + if (LOG.isDebugEnabled) { + p.addLibraryListener( object : LibraryListener { override fun libraryLoaded(e: LibraryEvent) { LOG.debug("Prolog library loaded " + e.libraryName) @@ -80,8 +80,12 @@ class LuconEngine override fun libraryUnloaded(e: LibraryEvent) { LOG.debug("Prolog library unloaded " + e.libraryName) } - }) - p.addSpyListener { l -> LOG.trace(l.msg + " " + l.source) } + } + ) + } + if (LOG.isTraceEnabled) { + p.addSpyListener { l -> LOG.trace(l.msg + " " + l.source) } + } p.addWarningListener { warningEvent -> val w = warningEvent.msg if (WARNING_FILTER.matcher(w).matches()) { @@ -101,7 +105,6 @@ class LuconEngine } catch (e: Exception) { LOG.error(e.message, e) } - } } @@ -111,7 +114,6 @@ class LuconEngine // should never happen throw RuntimeException("Error loading " + LuconLibrary::class.java.name, e) } - } fun setSpy(spy: Boolean) { @@ -121,14 +123,13 @@ class LuconEngine /** * Loads a policy in form of a prolog theory. * - * * Existing policies will be overwritten. * * @param theory The theory to load */ @Throws(InvalidTheoryException::class) fun loadPolicy(theory: String) { - val t = Theory(theory) + val t = Theory.parseWithStandardOperators(theory) LOG.debug("Loading theory:\n$t") p.theory = t } @@ -147,7 +148,6 @@ class LuconEngine } catch (e: NoSolutionException) { e.printStackTrace() } - } return result } @@ -189,7 +189,7 @@ class LuconEngine try { // Get policy as prolog, add Camel route and init new Prolog engine with combined theory val t = p.theory - t.append(Theory(routePl)) + t.append(Theory.parseWithStandardOperators(routePl)) val newP = Prolog() newP.loadLibrary(LuconLibrary()) newP.theory = t @@ -197,7 +197,8 @@ class LuconEngine // Generate the proof (=run query) val result = query(newP, QUERY_ROUTE_VERIFICATION, true) - // If a result has been found, this means there is at least one counterexample of a path in a + // If a result has been found, this means there is at least one counterexample of a path + // in a // route that violates a policy if (result.isNotEmpty()) { val ces = ArrayList(result.size) @@ -231,6 +232,4 @@ class LuconEngine defaultPolicy = theory } } - - } diff --git a/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconLibrary.kt b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconLibrary.kt new file mode 100644 index 000000000..98508d494 --- /dev/null +++ b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/LuconLibrary.kt @@ -0,0 +1,215 @@ +/*- + * ========================LICENSE_START================================= + * ids-dataflow-control + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.dataflowcontrol.lucon + +import alice.tuprolog.Library +import alice.tuprolog.Number +import alice.tuprolog.Term +import alice.tuprolog.Var +import com.google.common.cache.CacheBuilder +import com.google.common.cache.CacheLoader +import java.util.concurrent.ExecutionException +import java.util.concurrent.TimeUnit +import org.slf4j.LoggerFactory + +/** + * Plugins and default theories for tuProlog engine. + * + * @author Michael Lux (michael.lux@aisec.fraunhofer.de) + */ +@Suppress("FunctionName", "unused") +class LuconLibrary : Library() { + @Transient + private val regexCache = + CacheBuilder.newBuilder() + .expireAfterAccess(1, TimeUnit.DAYS) + .maximumWeight(1e6.toLong()) + .weigher { k, _ -> k.length } + .build( + object : CacheLoader() { + override fun load(key: String) = Regex(key, RegexOption.DOT_MATCHES_ALL) + } + ) + + override fun getTheory(): String = + """ +set_of(In, Out) :- % get a pairwise different, sorted set from a list + quicksort(In, '@<', Sorted), + no_duplicates(Sorted, Out). + +get_labels(Out) :- % collect and return asserted labels + once(setof(L, label(L), Out) ; Out = []). + +assert_labels(L, A) :- assert_labels(L, A, []). +assert_labels([], A, A). +assert_labels([L|Tail], Ar, A) :- label(L), assert_labels(Tail, Ar, A), !. +assert_labels([L|Tail], Ar, A) :- assert(label(L)), assert_labels(Tail, Ar, [L|A]). + +retract_labels(L, R) :- retract_labels(L, R, []). +retract_labels([], R, R). +retract_labels([L|Tail], Rr, R) :- retract(label(L)), retract_labels(Tail, Rr, [L|R]), !. +retract_labels([_|Tail], Rr, R) :- retract_labels(Tail, Rr, R). + +all_ground([]). +all_ground([Head|Tail]) :- ground(Head), all_ground(Tail). + +cache_put_all_unsafe(_, []). +cache_put_all_unsafe(KL, [V|T]) :- cache_put_unsafe(KL, V), cache_put_all_unsafe(KL, T). +cache_put_unsafe(KL, V) :- + %print(["CACHE PUT: "|[KL, V]]), nl, + assertz(cache_entry(KL, V)). + +cache_put_all(KL, VL) :- all_ground(KL), cache_put_all_unsafe(KL, VL). +cache_put(KL, V) :- cache_put_check(KL, V); true. +cache_put_check(KL, V) :- all_ground(KL), cache_put_unsafe(KL, V). + +cache_get(KL, V) :- + cache_entry(KL, V). + %-> print(["CACHE HIT: ", KL, V]), nl + %; print(["CACHE MISS: ", KL]), nl, fail. + +cache_clear(KL) :- retractall(cache_entry(KL, _)). + +action_service(Action, S) :- % Finds services S matching endpoints of N [ O(|Ep_S|) ] + has_endpoint(S, Regex), % a service S exists such that [ O(|Ep_S|) ] + regex_match(Regex, Action). % the action of A matches the endpoint of S [ assume O(1) ] + +collect_creates_labels([], []). +collect_creates_labels([S|SCTail], ACout) :- + collect_creates_labels(SCTail, ACnew), + findall(A, creates_label(S, A), AC), + once(bound(ACnew); ACnew = []), + append(AC, ACnew, ACout). + +collect_removes_labels([], []). +collect_removes_labels([S|SCTail], RCout) :- + collect_removes_labels(SCTail, RCnew), + findall(R, removes_label(S, R), RC), + once(bound(RCnew); RCnew = []), + append(RC, RCnew, RCout). + +update_labels(Act, Out, Aout, Rout) :- % Updates labels according to spec. of service S + once(setof(S, action_service(Act, S), SC); SC = []), % collect all relevant services + collect_creates_labels(SC, ACraw), set_of(ACraw, AC), assert_labels(AC, Aout), % assert new labels added by S + collect_removes_labels(SC, RCraw), set_of(RCraw, RC), retract_labels(RC, Rout), % retract labels removed by S + print([Act, "=>", SC, "added:", Aout, "removed:", Rout]),nl, + get_labels(Out). % collect and return asserted labels + +conflicting_rules(Act, Ri, Req, DC, PR) :- % Find conflicting rules [ O(|Ep_S| x |S -- R|) ] + action_service(Act, S2), % a service S2 [ O(|Ep_S|) ] + rule(R2), Ri \= R2, receives_label(R2), % with another VALID rule R2 + has_target(R2, S2), % that is targeting S2 [ O(|S -- R|) ] + has_decision(R2, D2), D2 \= Req, % which enforces a different decision, [ O(1) ] + rule_priority(R2, PR2), % and has priority PR2 [ O(1) ] + G =.. [DC, PR2, PR], call(G). % such that 'DC'(PR, PR2) is fulfilled [ O(1) ] + +dominant_rules(Act, Req, DC, S, R) :- % Find the dominant rule R for action Act (from cache) + get_labels(LC), % Collect currently asserted labels + cache_get([dr, Act, Req, DC, LC], V), % CACHE GET entry + list(V), V = [S, R]. % unpack result + +dominant_rules(Act, Req, DC, S, R) :- % Find the dominant rule R for action Act [ O(|Ep_S| x |S -- R|) ] + get_labels(LC), % Collect currently asserted labels + \+(cache_get([dr, Act, Req, DC, LC], _)), % CACHE GET entry + (setof(DomRule, ( + action_service(Act, Si), % Action Act is matched by a service Si [ O(|Ep_S|) ] + rule(Ri), receives_label(Ri), % There is a VALID rule Ri + has_target(Ri, Si), % targeting by service Si [ O(|S -- R|) ] + has_decision(Ri, Req), % with a decision that unifies with Require [ O(1) ] + rule_priority(Ri, PR), % that has priority PR, then [ O(1) ] + \+(conflicting_rules(Act, Ri, Req, DC, PR)), % there MUST NOT exist conflicting rules [ O(|Ep_S| x |S -- R|) ] + DomRule = [Si, Ri] % compose the result + ), RL) + -> cache_put_all([dr, Act, Req, DC, LC], RL) % IF successful, CACHE PUT ALL results + ; cache_put([dr, Act, Req, DC, LC], none) % ELSE CACHE PUT 'none' + ), !, % don't backtrack into the caching logic + dominant_rules(Act, Req, DC, S, R). % delegate to cache handler + +dominant_drop_rules(Act, S, R) :- dominant_rules(Act, drop, '>', S, R). +dominant_allow_rules(Act, S, R) :- dominant_rules(Act, allow, '>=', S, R). + +% Query for a path between two nodes and print the labels along the possible paths like so: +% +% path(stmt_1, stmt_5, Trace). +% +path(A,B,T) :- % Two nodes are connected if we can walk from A to B, + trace_walk(A, B, [[A, []]], T). % starting with empty label list + +trace_walk(A, B, Log, T) :- % We have walked from A to B and verify [ O(|Ep_S| x |S -- R|) ] + A = B, % A is the desired destination with [ O(1) ] + has_action(A, Act), % an action Act and there is [ O(1) ] + dominant_drop_rules(Act, S, R), % a dominant drop rule R and service S for Act [ O(|Ep_S| x |S -- R|) ] + receives_label(R), % R receives a set of labels with [ assume O(1) ] + get_labels(LC), % get asserted labels [ O(L_a), assume O(1) ] + T = [[S, LC, R]|Log]. % [unify the recursion result with Out] [ O(1) ] + %print("finished (END): "), print(A), nl. + +trace_walk(A, B, Log, T) :- % We can walk from A to B if [ O(|Ep_S| x |S -- R|) ] + succ(A, X), % A is connected to X and there is [ O(|succ(A, _)|), assume O(1) ] + has_action(A, Act), % an action Action and there is [ O(1) ] + dominant_allow_rules(Act, _, _), % a dominant allow rule and service S for Act [ O(|Ep_S| x |S -- R|) ] + update_labels(Act, LN, Aout, Rout), % [update the labels for the next step] [ O(|L|), assume O(1) ], + %print([Aout, Rout]), nl, + %print("transition: "), print([A, X, S, LN]), nl, + ( + trace_walk(X, B, [[X, LN]|Log], T) % we can get from X to B [ Recursion! ] + ; true % or otherwise, make sure that the cleanup stuff below gets called! + ), + retract_labels(Aout, _), % retract labels asserted before recursion + assert_labels(Rout, _), % assert labels retracted before recursion + %print("finished: "), print(A), nl, + ground(T). % If T is bound, recursion returned successfully, no result otherwise! + """.trimIndent() + + fun regex_match_2(regex: Term, input: Term): Boolean { + if (LOG.isTraceEnabled) { + LOG.trace("regex_match/2 called with $regex $input") + } + // Both regex and input string must be ground + return if (isComplex(regex) || isComplex(input)) { + false + } else + try { + val regexString = TuPrologHelper.unquote(regex.term.toString()) + val inputString = TuPrologHelper.unquote(input.term.toString()) + val match = regexCache[regexString].matches(inputString) + if (LOG.isTraceEnabled) { + LOG.trace("regex_match: $regexString , $inputString: $match") + } + match + } catch (e: ExecutionException) { + if (LOG.isWarnEnabled) { + LOG.warn(e.message, e) + } + false + } + } + + companion object { + private val LOG = LoggerFactory.getLogger(LuconLibrary::class.java) + private fun isComplex(term: Term): Boolean { + var t = term + if (t is Var) { + t = t.getTerm() + } + return (!t.isAtom || t.isList) && t !is Number + } + } +} diff --git a/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/TuPrologHelper.kt b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/TuPrologHelper.kt new file mode 100644 index 000000000..d6d8f5d2c --- /dev/null +++ b/ids-dataflow-control/src/main/kotlin/de/fhg/aisec/ids/dataflowcontrol/lucon/TuPrologHelper.kt @@ -0,0 +1,66 @@ +/*- + * ========================LICENSE_START================================= + * ids-dataflow-control + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.dataflowcontrol.lucon + +import alice.tuprolog.Struct +import alice.tuprolog.Term +import java.util.* +import java.util.stream.Stream +import java.util.stream.StreamSupport + +object TuPrologHelper { + + fun escape(s: String?): String { + if (s == null) { + return "" + } + val sb = StringBuilder() + sb.append('\'') + val charLength = s.length + for (i in 0 until charLength) { + val c = s[i] + sb.append(if (c == '\'') "''" else c) + } + sb.append('\'') + return sb.toString() + } + + fun listStream(list: Term?): Stream { + if (list == null) { + return Stream.empty() + } + require(list.isList) { "Not a tuProlog list" } + val listIterator = (list as Struct).listIterator() + return StreamSupport.stream( + Spliterators.spliteratorUnknownSize(listIterator, Spliterator.ORDERED), + false + ) + } + + fun unquote(s: String): String { + return if (s.length > 2 && s[0] == '\'' && s[s.length - 1] == '\'') { + s.substring(1, s.length - 1) + } else if (s.length == 2 && "''" == s) { + "" + } else { + s + } + } +} diff --git a/ids-dataflow-control/src/test/java/de/fhg/aisec/ids/dataflowcontrol/LuconEngineTest.java b/ids-dataflow-control/src/test/java/de/fhg/aisec/ids/dataflowcontrol/LuconEngineTest.java deleted file mode 100644 index 344a29081..000000000 --- a/ids-dataflow-control/src/test/java/de/fhg/aisec/ids/dataflowcontrol/LuconEngineTest.java +++ /dev/null @@ -1,673 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-dataflow-control - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.dataflowcontrol; - -import static org.junit.Assert.*; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import alice.tuprolog.InvalidTheoryException; -import alice.tuprolog.MalformedGoalException; -import alice.tuprolog.NoSolutionException; -import alice.tuprolog.SolveInfo; -import com.google.common.collect.Sets; -import de.fhg.aisec.ids.api.policy.*; -import de.fhg.aisec.ids.api.policy.PolicyDecision.Decision; -import de.fhg.aisec.ids.api.router.RouteManager; -import de.fhg.aisec.ids.api.router.RouteVerificationProof; -import de.fhg.aisec.ids.dataflowcontrol.lucon.LuconEngine; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import org.junit.Ignore; -import org.junit.Test; - -/** - * Unit tests for the LUCON policy engine. - * - * @author Julian Schuette (julian.schuette@aisec.fraunhofer.de) - */ -public class LuconEngineTest { - // Solving Towers of Hanoi in only two lines. Prolog FTW! - private static final String HANOI_THEORY = - "move(1,X,Y,_) :- " - + "write('Move top disk from '), write(X), write(' to '), write(Y), nl. \n" - + "move(N,X,Y,Z) :- N>1, M is N-1, move(M,X,Z,Y), move(1,X,Y,_), move(M,Z,Y,X). "; - - // A random but syntactically correct policy. - private static final String EXAMPLE_POLICY = - "\n" - + "%%%%%%%% Rules %%%%%%%%%%%%\n" - + "rule(denyAll).\n" - + "rule_priority(denyAll, 0).\n" - + "has_decision(denyAll, drop).\n" - + "receives_label(denyAll).\n" - + "has_target(denyAll, serviceAll).\n" - + "\n" - + "rule(allowRule).\n" - + "rule_priority(allowRule, 1).\n" - + "has_decision(allowRule, allow).\n" - + "receives_label(allowRule).\n" - + "has_target(allowRule, hiveMqttBrokerService).\n" - + "has_target(allowRule, anonymizerService).\n" - + "has_target(allowRule, loggerService).\n" - + "has_target(allowRule, hadoopClustersService).\n" - + "has_target(allowRule, testQueueService).\n" - + "\n" - + "rule(deleteAfterOneMonth).\n" - + "rule_priority(deleteAfterOneMonth, 1).\n" - + "has_decision(deleteAfterOneMonth, allow).\n" - + "receives_label(deleteAfterOneMonth) :- label(private).\n" - + "has_target(deleteAfterOneMonth, service78096644).\n" - + "has_obligation(deleteAfterOneMonth, obl1709554620).\n" - + "% generated service\n" - + "service(service78096644).\n" - + "has_endpoint(service78096644, \"hdfs.*\").\n" - + "% generated obligation\n" - + "requires_prerequisite(obl1709554620, delete_after_days(30)).\n" - + "has_alternativedecision(obl1709554620, drop).\n" - + "\n" - + "rule(anotherRule).\n" - + "rule_priority(anotherRule, 1).\n" - + "has_target(anotherRule, testQueueService).\n" - + "receives_label(anotherRule) :- label(private).\n" - + "has_decision(anotherRule, drop).\n" - + "\n" - + "%%%%%%%%%%%% Services %%%%%%%%%%%%\n" - + "service(serviceAll).\n" - + "has_endpoint(serviceAll,'.*').\n" - + "\n" - + "service(hiveMqttBrokerService).\n" - + "creates_label(hiveMqttBrokerService, labelone).\n" - + "creates_label(hiveMqttBrokerService, private).\n" - + "removes_label(hiveMqttBrokerService, labeltwo).\n" - + "has_endpoint(hiveMqttBrokerService, \"^paho:.*?tcp://broker.hivemq.com:1883.*\").\n" - + "has_property(hiveMqttBrokerService, type, public).\n" - + "\n" - + "service(anonymizerService).\n" - + "has_endpoint(anonymizerService, \".*anonymizer.*\").\n" - + "has_property(anonymizerService, myProp, anonymize('surname', 'name')).\n" - + "\n" - + "service(loggerService).\n" - + "has_endpoint(loggerService, \"^log.*\").\n" - + "\n" - + "service(hadoopClustersService).\n" - + "has_endpoint(hadoopClustersService, \"^hdfs://.*\").\n" - + "has_capability(hadoopClustersService, deletion).\n" - + "has_property(hadoopClustersService, anonymizes, anonymize('surname', 'name')).\n" - + "\n" - + "service(testQueueService).\n" - + "has_endpoint(testQueueService, \"^amqp:.*?:test\")."; - - // Policy with extended labels, i.e. "purpose(green)" - private static final String EXTENDED_LABELS_POLICY = - "" - + "%%%%%%%% Rules %%%%%%%%%%%%\n" - + "rule(denyAll).\n" - + "rule_priority(denyAll, 0).\n" - + "has_decision(denyAll, drop).\n" - + "receives_label(denyAll).\n" - + "has_target(denyAll, serviceAll).\n" - + "\n" - + "rule(demo).\n" - + "rule_priority(demo, 1).\n" - + "has_target(demo, service473016340).\n" - + "service(service473016340).\n" - + "has_endpoint(service473016340,\"(ahc|ahc-ws|cxf|cxfbean|cxfrs)://.*\").\n" - + "receives_label(demo) :- label(purpose(green)).\n" // Note that Prolog does not support - // nested predicates. - + "has_decision(demo, allow).\n" - + "\n" - + "%%%%% Services %%%%%%%%%%%%\n" - + "service(serviceAll).\n" - + "has_endpoint(serviceAll,'.*').\n" - + "creates_label(serviceAll, purpose(green)).\n" - + "\n" - + "service(sanitizedata).\n" - + "has_endpoint(sanitizedata, \"^bean://SanitizerBean.*\").\n" - + "creates_label(sanitizedata, public).\n" - + "removes_label(sanitizedata, private).\n"; - - // Route from LUCON paper with path searching logic - private static final String VERIFIABLE_ROUTE = - "%\n" - + "% (C) Julian Schütte, Fraunhofer AISEC, 2017\n" - + "%\n" - + "% Demonstration of model checking a message route against a usage control policy\n" - + "%\n" - + "% Message Route definition\n" - + "%\n" - + "% hiveMqttBroker \n" - + "% / \\ \n" - + "% logger anonymizer \n" - + "% \\ / \n" - + "% hadoopClusters \n" - + "% | \n" - + "% testQueue \n" - + "entrynode(hiveMqttBroker).\n" - + "stmt(hiveMqttBroker).\n" - + "has_action(hiveMqttBroker, \"paho:something:tcp://broker.hivemq.com:1883/anywhere\").\n" - + "stmt(logger).\n" - + "has_action(logger, \"log\").\n" - + "stmt(anonymizer).\n" - + "has_action(anonymizer, \"hello_anonymizer_world\").\n" - + "stmt(hadoopClusters).\n" - + "has_action(hadoopClusters, \"hdfs://myCluser\").\n" - + "stmt(testQueue).\n" - + "has_action(testQueue, \"amqp:testQueue:test\").\n" - + "\n" - + "succ(hiveMqttBroker, logger).\n" - + "succ(hiveMqttBroker, anonymizer).\n" - + "succ(logger, hadoopClusters).\n" - + "succ(anonymizer, hadoopClusters).\n" - + "succ(hadoopClusters, testQueue).\n" - + "\n"; - - /** - * Loading a valid Prolog theory should not fail. - * - * @throws InvalidTheoryException If invalid theory is encountered - */ - @Test - public void testLoadingTheoryGood() throws InvalidTheoryException { - LuconEngine e = new LuconEngine(null); - e.loadPolicy(HANOI_THEORY); - String json = e.getTheoryAsJSON(); - assertTrue(json.startsWith("{\"theory\":\"move(1,X,Y,")); - String prolog = e.getTheory(); - assertTrue(prolog.trim().startsWith("move(1,X,Y")); - } - - /** Loading an invalid Prolog theory is expected to throw an exception. */ - @Test - public void testLoadingTheoryNotGood() { - LuconEngine e = new LuconEngine(System.out); - try { - e.loadPolicy("This is invalid"); - } catch (InvalidTheoryException ex) { - return; // Expected - } - fail("Could load invalid theory without exception"); - } - - /** - * Solve a simple Prolog puzzle. - * - * @throws InvalidTheoryException If invalid theory is encountered - */ - @Test - public void testSimplePrologQuery() throws InvalidTheoryException { - LuconEngine e = new LuconEngine(System.out); - e.loadPolicy(HANOI_THEORY); - try { - List solutions = e.query("move(3,left,right,center). ", true); - assertEquals(1, solutions.size()); - for (SolveInfo solution : solutions) { - System.out.println(solution.getSolution().toString()); - System.out.println(solution.hasOpenAlternatives()); - - System.out.println(solution.isSuccess()); - } - } catch (MalformedGoalException | NoSolutionException e1) { - e1.printStackTrace(); - fail(e1.getMessage()); - } - } - - /** - * Run some simple queries against an actual policy. - * - * @throws InvalidTheoryException If invalid theory is encountered - */ - @Test - public void testSolve2() throws InvalidTheoryException { - LuconEngine e = new LuconEngine(System.out); - e.loadPolicy(EXAMPLE_POLICY); - try { - List solutions = - e.query("has_endpoint(X,Y),regex_match(Y, \"hdfs://myendpoint\").", true); - assertNotNull(solutions); - assertEquals(3, solutions.size()); - for (SolveInfo solution : solutions) { - System.out.println(solution.getSolution().toString()); - System.out.println(solution.hasOpenAlternatives()); - System.out.println(solution.isSuccess()); - } - } catch (MalformedGoalException | NoSolutionException e1) { - e1.printStackTrace(); - fail(e1.getMessage()); - } - } - - /** - * Test if the correct policy decisions are taken for a (very) simple route and an example policy. - */ - @Test - public void testPolicyDecision() { - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - pdp.loadPolicy(EXAMPLE_POLICY); - - // Simple message context with nonsense attributes - Map attributes = new HashMap<>(); - attributes.put("some_message_key", "some_message_value"); - attributes.put(PDP.LABELS_KEY, Sets.newHashSet("private")); - - // Simple source and dest nodes - ServiceNode source = new ServiceNode("seda:test_source", null, null); - ServiceNode dest = new ServiceNode("hdfs://some_url", null, null); - - PolicyDecision dec = pdp.requestDecision(new DecisionRequest(source, dest, attributes, null)); - assertEquals(Decision.ALLOW, dec.getDecision()); - - // // Check obligation - // assertEquals(3, dec.getObligations().size()); - // Obligation obl = dec.getObligations().get(0); - // assertEquals("delete_after_days(30)", obl.getAction()); - } - - /** - * Test if the correct policy decisions are taken for a (very) simple route and an example policy. - */ - @Test - public void testPolicyDecisionWithExtendedLabels() { - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - pdp.loadPolicy(EXTENDED_LABELS_POLICY); - - // Simple message context with nonsense attributes - Map attributes = new HashMap<>(); - attributes.put("some_message_key", "some_message_value"); - attributes.put(PDP.LABELS_KEY, Sets.newHashSet("purpose(green)")); - - // Simple source and dest nodes - ServiceNode source = new ServiceNode("seda:test_source", null, null); - ServiceNode dest = new ServiceNode("ahc://some_url", null, null); - - PolicyDecision dec = pdp.requestDecision(new DecisionRequest(source, dest, attributes, null)); - assertEquals(Decision.ALLOW, dec.getDecision()); - - // Check obligation - assertEquals(0, dec.getObligations().size()); - } - - /** List all rules of the currently loaded policy. */ - @Test - public void testListRules() { - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - - // Without any policy, we expect an empty list of rules - List emptyList = pdp.listRules(); - assertNotNull(emptyList); - assertTrue(emptyList.isEmpty()); - - // Load a policy - pdp.loadPolicy(EXAMPLE_POLICY); - - // We now expect 3 rules - List rules = pdp.listRules(); - assertNotNull(rules); - assertEquals(4, rules.size()); - assertTrue(rules.contains("deleteAfterOneMonth")); - assertTrue(rules.contains("anotherRule")); - } - - @Test - public void testTransformationsMatch() { - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - pdp.loadPolicy(EXAMPLE_POLICY); - ServiceNode node = new ServiceNode("paho:tcp://broker.hivemq.com:1883/blablubb", null, null); - TransformationDecision trans = pdp.requestTranformations(node); - - assertNotNull(trans); - assertNotNull(trans.getLabelsToAdd()); - assertNotNull(trans.getLabelsToRemove()); - - assertEquals(2, trans.getLabelsToAdd().size()); - assertEquals(1, trans.getLabelsToRemove().size()); - - assertTrue(trans.getLabelsToAdd().contains("labelone")); - assertTrue(trans.getLabelsToRemove().contains("labeltwo")); - } - - @Test - public void testTransformationsNomatch() { - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - pdp.loadPolicy(EXAMPLE_POLICY); - ServiceNode node = new ServiceNode("someendpointwhichisnotmatchedbypolicy", null, null); - TransformationDecision trans = pdp.requestTranformations(node); - - assertNotNull(trans); - assertNotNull(trans.getLabelsToAdd()); - assertNotNull(trans.getLabelsToRemove()); - - assertEquals(0, trans.getLabelsToAdd().size()); - assertEquals(0, trans.getLabelsToRemove().size()); - } - - /** - * Tests the generation of a proof that a route matches a policy. - * - * @throws Exception If something fails - */ - @Test - public void testVerifyRoute() throws Exception { - // Create RouteManager returning VERIFIABLE_ROUTE - RouteManager rm = mock(RouteManager.class); - System.out.println("------ ROUTE ----------"); - System.out.println(VERIFIABLE_ROUTE); - when(rm.getRouteAsProlog(anyString())).thenReturn(VERIFIABLE_ROUTE); - - // Create policy decision point and attach to route manager - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - - // Manually inject routemanager into PDP - Field f1 = pdp.getClass().getDeclaredField("routeManager"); - f1.setAccessible(true); - f1.set(pdp, rm); - - // Load policy - pdp.loadPolicy(EXAMPLE_POLICY); - - // Verify VERIFIABLE_ROUTE against EXAMPLE_POLICY - RouteVerificationProof proof = pdp.verifyRoute("mockId"); - System.out.println("------ Proof follows ----------"); - System.out.println(proof != null ? proof.toString() : null); - assertNotNull(proof); - assertFalse(proof.isValid()); - // assertTrue(proof.toString().contains("Service testQueueService may receive messages labeled - // [private], " + "which is forbidden by rule \"anotherRule\".")); - System.out.println("##### PROBLEM #####"); - System.out.println(proof.toString()); - assertTrue( - proof - .toString() - .contains( - "Service testQueueService may receive messages, which is forbidden by rule \"anotherRule\".")); - assertNotNull(proof.getCounterExamples()); - } - - @Test - @Ignore("Not a regular unit test; for evaluating runtime performance.") - public void testPerformanceEvaluationScaleRules() { - for (int i = 10; i <= 5000; i += 10) { - // Load n test rules into PDP - String theory = generateRules(i); - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - long start = System.nanoTime(); - pdp.loadPolicy(theory); - long stop = System.nanoTime(); - long loadTime = (stop - start); - - // Simple message context with nonsense attributes - Map attributes = new HashMap<>(); - attributes.put("some_message_key", "some_message_value"); - - // Simple source and dest nodes - ServiceNode source = new ServiceNode("seda:test_source", null, null); - ServiceNode dest = new ServiceNode("hdfs://some_url", null, null); - - start = System.nanoTime(); - PolicyDecision dec = pdp.requestDecision(new DecisionRequest(source, dest, attributes, null)); - stop = System.nanoTime(); - long queryTime = stop - start; - - System.out.println(i + "\t\t" + loadTime + "\t\t" + queryTime); - assertEquals(Decision.ALLOW, dec.getDecision()); - } - } - - @Test - @Ignore("Not a regular unit test; for evaluating runtime performance.") - public void testPerformanceEvaluationScaleLabels() { - for (int i = 0; i <= 5000; i += 10) { - // Load n test rules into PDP - String theory = generateLabels(i); - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - long start = System.nanoTime(); - pdp.loadPolicy(theory); - long stop = System.nanoTime(); - long loadTime = (stop - start); - - // Simple message context with nonsense attributes - Map attributes = new HashMap<>(); - attributes.put("some_message_key", "some_message_value"); - - // Simple source and dest nodes - ServiceNode source = new ServiceNode("seda:test_source", null, null); - ServiceNode dest = new ServiceNode("hdfs://some_url", null, null); - - start = System.nanoTime(); - PolicyDecision dec = pdp.requestDecision(new DecisionRequest(source, dest, attributes, null)); - stop = System.nanoTime(); - long queryTime = stop - start; - - System.out.println(i + "\t\t" + loadTime + "\t\t" + queryTime); - assertEquals(Decision.ALLOW, dec.getDecision()); - } - } - - @Test - @Ignore("Not a regular unit test; for evaluating runtime performance.") - public void testmemoryEvaluationScaleRules() { - for (int i = 10; i <= 5000; i += 10) { - // Load n test rules into PDP - String theory = generateRules(i); - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - pdp.loadPolicy(theory); - - // Simple message context with nonsense attributes - Map attributes = new HashMap<>(); - attributes.put("some_message_key", "some_message_value"); - - // Simple source and dest nodes - ServiceNode source = new ServiceNode("seda:test_source", null, null); - ServiceNode dest = new ServiceNode("hdfs://some_url", null, null); - - System.gc(); - System.gc(); - System.gc(); // Empty level 1- & 2-LRUs. - long memoryBefore = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - PolicyDecision dec = pdp.requestDecision(new DecisionRequest(source, dest, attributes, null)); - long memoryAfter = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - System.gc(); - System.gc(); - System.gc(); // Empty level 1- & 2-LRUs. - long memoryAfterGC = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - - System.out.println( - i + "\t\t" + (memoryAfter - memoryBefore) + "\t\t" + (memoryAfterGC - memoryBefore)); - assertEquals(Decision.ALLOW, dec.getDecision()); - } - } - - @Test - @Ignore("Not a regular unit test; for evaluating runtime performance.") - public void testmemoryEvaluationScaleLabels() { - for (int i = 10; i <= 5000; i += 10) { - // Load n test rules into PDP - String theory = generateLabels(i); - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - pdp.loadPolicies(); - pdp.loadPolicy(theory); - - // Simple message context with nonsense attributes - Map attributes = new HashMap<>(); - attributes.put("some_message_key", "some_message_value"); - - // Simple source and dest nodes - ServiceNode source = new ServiceNode("seda:test_source", null, null); - ServiceNode dest = new ServiceNode("hdfs://some_url", null, null); - - System.gc(); - System.gc(); - System.gc(); // Empty level 1- & 2-LRUs. - long memoryBefore = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - PolicyDecision dec = pdp.requestDecision(new DecisionRequest(source, dest, attributes, null)); - long memoryAfter = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - System.gc(); - System.gc(); - System.gc(); // Empty level 1- & 2-LRUs. - long memoryAfterGC = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); - - System.out.println( - i + "\t\t" + (memoryAfter - memoryBefore) + "\t\t" + (memoryAfterGC - memoryBefore)); - assertEquals(Decision.ALLOW, dec.getDecision()); - } - } - - @Test - public void testRulePriorities() { - PolicyDecisionPoint pdp = new PolicyDecisionPoint(); - // Load test policy w/ two rules - InputStream policy = this.getClass().getClassLoader().getResourceAsStream("policy-example.pl"); - assertNotNull(policy); - pdp.loadPolicy(new Scanner(policy, StandardCharsets.UTF_8.name()).useDelimiter("\\A").next()); - assertEquals(2, pdp.listRules().size()); - - // Test order of specification in rule file - String ruleThree = pdp.listRules().get(0); - assertEquals("testRulePrioThree", ruleThree); - String ruleTwo = pdp.listRules().get(1); - assertEquals("testRulePrioTwo", ruleTwo); - - // FALL-THROUGH: Test fall-through decision (no msg label matches) - ServiceNode from = new ServiceNode("IAmMatchedByRuleThreeOnly", null, null); - ServiceNode to = new ServiceNode("hdfs://IAmMatchedByBothRules", null, null); - Map msgCtx = new HashMap<>(); - Map envCtx = new HashMap<>(); - DecisionRequest req = new DecisionRequest(from, to, msgCtx, envCtx); - PolicyDecision dec = pdp.requestDecision(req); - assertNotNull(dec); - Decision d = dec.getDecision(); - assertEquals(Decision.DENY, d); - assertEquals("No matching rule", dec.getReason()); - - // FALL-THROUGH: presence of a label "public" (w/o any specific value) does not yet trigger - // testRulePrioTwo, because label "filtered" is required in addition. - from = new ServiceNode("IAmMatchedByRuleThreeOnly", null, null); - to = new ServiceNode("hdfs://IAmMatchedByBothRules", null, null); - msgCtx = new HashMap<>(); - msgCtx.put(PDP.LABELS_KEY, Sets.newHashSet("public")); - envCtx = new HashMap<>(); - req = new DecisionRequest(from, to, msgCtx, envCtx); - dec = pdp.requestDecision(req); - assertNotNull(dec); - d = dec.getDecision(); - assertEquals(Decision.DENY, d); - assertEquals("No matching rule", dec.getReason()); - - // testRulePrioTwo: now we have labels "public" AND "filtered" set, which makes testRulePrioTwo - // match - from = new ServiceNode("IAmMatchedByRuleThreeOnly", null, null); - to = new ServiceNode("hdfs://IAmMatchedByBothRules", null, null); - msgCtx = new HashMap<>(); - msgCtx.put(PDP.LABELS_KEY, Sets.newHashSet("public", "filtered")); - envCtx = new HashMap<>(); - req = new DecisionRequest(from, to, msgCtx, envCtx); - dec = pdp.requestDecision(req); - assertNotNull(dec); - d = dec.getDecision(); - assertEquals(Decision.ALLOW, d); - assertEquals("testRulePrioTwo", dec.getReason()); - - // testRulePrioTwo: "public" AND "filtered" makes testRulePrioTwo match. Additional labels do - // not harm - from = new ServiceNode("IAmMatchedByRuleThreeOnly", null, null); - to = new ServiceNode("hdfs://IAmMatchedByBothRules", null, null); - msgCtx = new HashMap<>(); - msgCtx.put(PDP.LABELS_KEY, Sets.newHashSet("public", "unusedlabel")); - envCtx = new HashMap<>(); - req = new DecisionRequest(from, to, msgCtx, envCtx); - dec = pdp.requestDecision(req); - assertNotNull(dec); - d = dec.getDecision(); - assertEquals(Decision.DENY, d); - assertEquals("No matching rule", dec.getReason()); - - // testRulePrioTwo: labels "public", "filtered", "private" will trigger testRulePrioOne and - // testRulePrioTwo. Rule with higher prio wins. - from = new ServiceNode("IAmMatchedByRuleThreeOnly", null, null); - to = new ServiceNode("hdfs://IAmMatchedByBothRules", null, null); - msgCtx = new HashMap<>(); - msgCtx.put(PDP.LABELS_KEY, Sets.newHashSet("public", "unusedlabel", "private")); - envCtx = new HashMap<>(); - req = new DecisionRequest(from, to, msgCtx, envCtx); - dec = pdp.requestDecision(req); - assertNotNull(dec); - d = dec.getDecision(); - assertEquals(Decision.DENY, d); - assertEquals("testRulePrioThree", dec.getReason()); - } - - /** - * Generates n random rules matching a target endpoint (given as regex). - * - *

All rules will take an "allow" decision. - * - * @param n The number of rules to generate - * @return The rules as String - */ - private String generateRules(int n) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < n; i++) { - String ruleName = "testRule" + i; - String targetName = "testTarget" + i; - String labelName = "label" + i; - sb.append("rule(").append(ruleName).append(").\n"); - sb.append("has_decision(").append(ruleName).append(", allow).\n"); - sb.append("has_alternativedecision(").append(ruleName).append(", allow).\n"); - sb.append("receives_label(").append(ruleName).append(").\n"); - sb.append("has_target(").append(ruleName).append(", ").append(targetName).append(").\n"); - sb.append("has_obligation(") - .append(ruleName) - .append(", testObligation") - .append(i) - .append(").\n"); - sb.append("service(").append(targetName).append(").\n"); - sb.append("has_endpoint(").append(targetName).append(", \".*\").\n"); - sb.append("creates_label(").append(targetName).append(", ").append(labelName).append(").\n"); - sb.append("removes_label(").append(targetName).append(", ").append(labelName).append(").\n"); - } - return sb.toString(); - } - - private String generateLabels(int n) { - StringBuilder sb = new StringBuilder(); - sb.append(generateRules(50)); - for (int i = 0; i < n; i++) { - sb.append("creates_label(testTarget1, labelX").append(i).append(").\n"); - sb.append("removes_label(testTarget1, labelX").append(i).append(").\n"); - } - return sb.toString(); - } -} diff --git a/ids-dataflow-control/src/test/kotlin/de/fhg/aisec/ids/dataflowcontrol/LuconEngineTest.kt b/ids-dataflow-control/src/test/kotlin/de/fhg/aisec/ids/dataflowcontrol/LuconEngineTest.kt new file mode 100644 index 000000000..b3427fb92 --- /dev/null +++ b/ids-dataflow-control/src/test/kotlin/de/fhg/aisec/ids/dataflowcontrol/LuconEngineTest.kt @@ -0,0 +1,667 @@ +/*- + * ========================LICENSE_START================================= + * ids-dataflow-control + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.dataflowcontrol + +import alice.tuprolog.exceptions.InvalidTheoryException +import alice.tuprolog.exceptions.MalformedGoalException +import alice.tuprolog.exceptions.NoSolutionException +import de.fhg.aisec.ids.api.policy.DecisionRequest +import de.fhg.aisec.ids.api.policy.PolicyDecision +import de.fhg.aisec.ids.api.policy.ServiceNode +import de.fhg.aisec.ids.api.router.RouteManager +import de.fhg.aisec.ids.dataflowcontrol.lucon.LuconEngine +import java.nio.charset.StandardCharsets +import java.util.* +import org.junit.Assert +import org.junit.Ignore +import org.junit.Test +import org.mockito.ArgumentMatchers +import org.mockito.Mockito + +/** + * Unit tests for the LUCON policy engine. + * + * @author Julian Schuette (julian.schuette@aisec.fraunhofer.de) + */ +class LuconEngineTest { + /** + * Loading a valid Prolog theory should not fail. + * + * @throws InvalidTheoryException If invalid theory is encountered + */ + @Test + @Throws(InvalidTheoryException::class) + fun testLoadingTheoryGood() { + val e = LuconEngine(null) + e.loadPolicy(HANOI_THEORY) + val prolog = e.theory + Assert.assertTrue(prolog.trim { it <= ' ' }.startsWith("move(1,X,Y")) + } + + /** Loading an invalid Prolog theory is expected to throw an exception. */ + @Test + fun testLoadingTheoryNotGood() { + val e = LuconEngine(System.out) + try { + e.loadPolicy("This is invalid") + } catch (ex: InvalidTheoryException) { + return // Expected + } + Assert.fail("Could load invalid theory without exception") + } + + /** + * Solve a simple Prolog puzzle. + * + * @throws InvalidTheoryException If invalid theory is encountered + */ + @Test + @Throws(InvalidTheoryException::class) + fun testSimplePrologQuery() { + val e = LuconEngine(System.out) + e.loadPolicy(HANOI_THEORY) + try { + val solutions = e.query("move(3,left,right,center). ", true) + Assert.assertEquals(1, solutions.size.toLong()) + for (solution in solutions) { + println(solution.solution.toString()) + println(solution.hasOpenAlternatives()) + println(solution.isSuccess) + } + } catch (e1: MalformedGoalException) { + e1.printStackTrace() + Assert.fail(e1.message) + } catch (e1: NoSolutionException) { + e1.printStackTrace() + Assert.fail(e1.message) + } + } + + /** + * Run some simple queries against an actual policy. + * + * @throws InvalidTheoryException If invalid theory is encountered + */ + @Test + @Throws(InvalidTheoryException::class) + fun testSolve2() { + val e = LuconEngine(System.out) + e.loadPolicy(EXAMPLE_POLICY) + try { + val solutions = + e.query("has_endpoint(X,Y),regex_match(Y, \"hdfs://myendpoint\").", true) + Assert.assertNotNull(solutions) + Assert.assertEquals(3, solutions.size.toLong()) + for (solution in solutions) { + println(solution.solution.toString()) + println(solution.hasOpenAlternatives()) + println(solution.isSuccess) + } + } catch (e1: MalformedGoalException) { + e1.printStackTrace() + Assert.fail(e1.message) + } catch (e1: NoSolutionException) { + e1.printStackTrace() + Assert.fail(e1.message) + } + } + + /** + * Test if the correct policy decisions are taken for a (very) simple route and an example + * policy. + */ + @Test + fun testPolicyDecision() { + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + pdp.loadPolicy(EXAMPLE_POLICY) + + // Simple source and dest nodes + val source = ServiceNode("seda:test_source", null, null) + val dest = ServiceNode("hdfs://some_url", null, null) + val dec = pdp.requestDecision(DecisionRequest(source, dest, setOf("private"), null)) + Assert.assertEquals(PolicyDecision.Decision.ALLOW, dec.decision) + + // // Check obligation + // assertEquals(3, dec.getObligations().size()); + // Obligation obl = dec.getObligations().get(0); + // assertEquals("delete_after_days(30)", obl.getAction()); + } + + /** + * Test if the correct policy decisions are taken for a (very) simple route and an example + * policy. + */ + @Test + fun testPolicyDecisionWithExtendedLabels() { + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + pdp.loadPolicy(EXTENDED_LABELS_POLICY) + + // Simple source and dest nodes + val source = ServiceNode("seda:test_source", null, null) + val dest = ServiceNode("ahc://some_url", null, null) + val dec = pdp.requestDecision(DecisionRequest(source, dest, setOf("purpose(green)"), null)) + Assert.assertEquals(PolicyDecision.Decision.ALLOW, dec.decision) + + // Check obligation + Assert.assertEquals(0, dec.obligations.size.toLong()) + } + + /** List all rules of the currently loaded policy. */ + @Test + fun testListRules() { + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + + // Without any policy, we expect an empty list of rules + val emptyList = pdp.listRules() + Assert.assertNotNull(emptyList) + Assert.assertTrue(emptyList.isEmpty()) + + // Load a policy + pdp.loadPolicy(EXAMPLE_POLICY) + + // We now expect 3 rules + val rules = pdp.listRules() + Assert.assertNotNull(rules) + Assert.assertEquals(4, rules.size.toLong()) + Assert.assertTrue(rules.contains("deleteAfterOneMonth")) + Assert.assertTrue(rules.contains("anotherRule")) + } + + @Test + fun testTransformationsMatch() { + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + pdp.loadPolicy(EXAMPLE_POLICY) + val node = ServiceNode("paho:tcp://broker.hivemq.com:1883/blablubb", null, null) + val trans = pdp.requestTranformations(node) + Assert.assertNotNull(trans) + Assert.assertNotNull(trans.labelsToAdd) + Assert.assertNotNull(trans.labelsToRemove) + Assert.assertEquals(2, trans.labelsToAdd.size.toLong()) + Assert.assertEquals(1, trans.labelsToRemove.size.toLong()) + Assert.assertTrue(trans.labelsToAdd.contains("labelone")) + Assert.assertTrue(trans.labelsToRemove.contains("labeltwo")) + } + + @Test + fun testTransformationsNomatch() { + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + pdp.loadPolicy(EXAMPLE_POLICY) + val node = ServiceNode("someendpointwhichisnotmatchedbypolicy", null, null) + val trans = pdp.requestTranformations(node) + Assert.assertNotNull(trans) + Assert.assertNotNull(trans.labelsToAdd) + Assert.assertNotNull(trans.labelsToRemove) + Assert.assertEquals(0, trans.labelsToAdd.size.toLong()) + Assert.assertEquals(0, trans.labelsToRemove.size.toLong()) + } + + /** + * Tests the generation of a proof that a route matches a policy. + * + * @throws Exception If something fails + */ + @Test + @Throws(Exception::class) + fun testVerifyRoute() { + // Create RouteManager returning VERIFIABLE_ROUTE + val rm = Mockito.mock(RouteManager::class.java) + println("------ ROUTE ----------") + println(VERIFIABLE_ROUTE) + Mockito.`when`(rm.getRouteAsProlog(ArgumentMatchers.anyString())) + .thenReturn(VERIFIABLE_ROUTE) + + // Create policy decision point and attach to route manager + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + + // Manually inject routemanager into PDP + val f1 = pdp.javaClass.getDeclaredField("routeManager") + f1.isAccessible = true + f1[pdp] = rm + + // Load policy + pdp.loadPolicy(EXAMPLE_POLICY) + + // Verify VERIFIABLE_ROUTE against EXAMPLE_POLICY + val proof = pdp.verifyRoute("mockId") + println("------ Proof follows ----------") + println(proof?.toString()) + Assert.assertNotNull(proof) + Assert.assertFalse(proof!!.isValid) + // assertTrue(proof.toString().contains("Service testQueueService may receive messages + // labeled + // [private], " + "which is forbidden by rule \"anotherRule\".")); + println("##### PROBLEM #####") + println(proof.toString()) + Assert.assertTrue( + proof + .toString() + .contains( + "Service testQueueService may receive messages, which is forbidden by rule \"anotherRule\"." + ) + ) + Assert.assertNotNull(proof.counterExamples) + } + + @Test + @Ignore("Not a regular unit test; for evaluating runtime performance.") + fun testPerformanceEvaluationScaleRules() { + var i = 10 + while (i <= 5000) { + + // Load n test rules into PDP + val theory = generateRules(i) + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + var start = System.nanoTime() + pdp.loadPolicy(theory) + var stop = System.nanoTime() + val loadTime = stop - start + + // Simple source and dest nodes + val source = ServiceNode("seda:test_source", null, null) + val dest = ServiceNode("hdfs://some_url", null, null) + start = System.nanoTime() + val dec = pdp.requestDecision(DecisionRequest(source, dest, emptySet(), null)) + stop = System.nanoTime() + val queryTime = stop - start + println(i.toString() + "\t\t" + loadTime + "\t\t" + queryTime) + Assert.assertEquals(PolicyDecision.Decision.ALLOW, dec.decision) + i += 10 + } + } + + @Test + @Ignore("Not a regular unit test; for evaluating runtime performance.") + fun testPerformanceEvaluationScaleLabels() { + var i = 0 + while (i <= 5000) { + + // Load n test rules into PDP + val theory = generateLabels(i) + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + var start = System.nanoTime() + pdp.loadPolicy(theory) + var stop = System.nanoTime() + val loadTime = stop - start + + // Simple source and dest nodes + val source = ServiceNode("seda:test_source", null, null) + val dest = ServiceNode("hdfs://some_url", null, null) + start = System.nanoTime() + val dec = pdp.requestDecision(DecisionRequest(source, dest, emptySet(), null)) + stop = System.nanoTime() + val queryTime = stop - start + println(i.toString() + "\t\t" + loadTime + "\t\t" + queryTime) + Assert.assertEquals(PolicyDecision.Decision.ALLOW, dec.decision) + i += 10 + } + } + + @Test + @Ignore("Not a regular unit test; for evaluating runtime performance.") + fun testmemoryEvaluationScaleRules() { + var i = 10 + while (i <= 5000) { + + // Load n test rules into PDP + val theory = generateRules(i) + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + pdp.loadPolicy(theory) + + // Simple source and dest nodes + val source = ServiceNode("seda:test_source", null, null) + val dest = ServiceNode("hdfs://some_url", null, null) + System.gc() + System.gc() + System.gc() // Empty level 1- & 2-LRUs. + val memoryBefore = + Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() + val dec = pdp.requestDecision(DecisionRequest(source, dest, emptySet(), null)) + val memoryAfter = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() + System.gc() + System.gc() + System.gc() // Empty level 1- & 2-LRUs. + val memoryAfterGC = + Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() + println( + i.toString() + + "\t\t" + + (memoryAfter - memoryBefore) + + "\t\t" + + (memoryAfterGC - memoryBefore) + ) + Assert.assertEquals(PolicyDecision.Decision.ALLOW, dec.decision) + i += 10 + } + } + + @Test + @Ignore("Not a regular unit test; for evaluating runtime performance.") + fun testmemoryEvaluationScaleLabels() { + var i = 10 + while (i <= 5000) { + + // Load n test rules into PDP + val theory = generateLabels(i) + val pdp = PolicyDecisionPoint() + pdp.loadPolicies() + pdp.loadPolicy(theory) + + // Simple source and dest nodes + val source = ServiceNode("seda:test_source", null, null) + val dest = ServiceNode("hdfs://some_url", null, null) + System.gc() + System.gc() + System.gc() // Empty level 1- & 2-LRUs. + val memoryBefore = + Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() + val dec = pdp.requestDecision(DecisionRequest(source, dest, emptySet(), null)) + val memoryAfter = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() + System.gc() + System.gc() + System.gc() // Empty level 1- & 2-LRUs. + val memoryAfterGC = + Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() + println( + i.toString() + + "\t\t" + + (memoryAfter - memoryBefore) + + "\t\t" + + (memoryAfterGC - memoryBefore) + ) + Assert.assertEquals(PolicyDecision.Decision.ALLOW, dec.decision) + i += 10 + } + } + + @Test + fun testRulePriorities() { + val pdp = PolicyDecisionPoint() + // Load test policy w/ two rules + val policy = this.javaClass.classLoader.getResourceAsStream("policy-example.pl") + Assert.assertNotNull(policy) + pdp.loadPolicy(Scanner(policy!!, StandardCharsets.UTF_8.name()).useDelimiter("\\A").next()) + Assert.assertEquals(2, pdp.listRules().size.toLong()) + + // Test order of specification in rule file + val ruleThree = pdp.listRules()[0] + Assert.assertEquals("testRulePrioThree", ruleThree) + val ruleTwo = pdp.listRules()[1] + Assert.assertEquals("testRulePrioTwo", ruleTwo) + + // FALL-THROUGH: Test fall-through decision (no msg label matches) + var from = ServiceNode("IAmMatchedByRuleThreeOnly", null, null) + var to = ServiceNode("hdfs://IAmMatchedByBothRules", null, null) + var envCtx: Map = HashMap() + var req = DecisionRequest(from, to, emptySet(), envCtx) + var dec = pdp.requestDecision(req) + Assert.assertNotNull(dec) + var d = dec.decision + Assert.assertEquals(PolicyDecision.Decision.DENY, d) + Assert.assertEquals("No matching rule", dec.reason) + + // FALL-THROUGH: presence of a label "public" (w/o any specific value) does not yet trigger + // testRulePrioTwo, because label "filtered" is required in addition. + from = ServiceNode("IAmMatchedByRuleThreeOnly", null, null) + to = ServiceNode("hdfs://IAmMatchedByBothRules", null, null) + envCtx = HashMap() + req = DecisionRequest(from, to, setOf("public"), envCtx) + dec = pdp.requestDecision(req) + Assert.assertNotNull(dec) + d = dec.decision + Assert.assertEquals(PolicyDecision.Decision.DENY, d) + Assert.assertEquals("No matching rule", dec.reason) + + // testRulePrioTwo: now we have labels "public" AND "filtered" set, which makes + // testRulePrioTwo + // match + from = ServiceNode("IAmMatchedByRuleThreeOnly", null, null) + to = ServiceNode("hdfs://IAmMatchedByBothRules", null, null) + envCtx = HashMap() + req = DecisionRequest(from, to, setOf("public", "filtered"), envCtx) + dec = pdp.requestDecision(req) + Assert.assertNotNull(dec) + d = dec.decision + Assert.assertEquals(PolicyDecision.Decision.ALLOW, d) + Assert.assertEquals("testRulePrioTwo", dec.reason) + + // testRulePrioTwo: "public" AND "filtered" makes testRulePrioTwo match. Additional labels + // do + // not harm + from = ServiceNode("IAmMatchedByRuleThreeOnly", null, null) + to = ServiceNode("hdfs://IAmMatchedByBothRules", null, null) + envCtx = HashMap() + req = DecisionRequest(from, to, setOf("public", "unusedlabel"), envCtx) + dec = pdp.requestDecision(req) + Assert.assertNotNull(dec) + d = dec.decision + Assert.assertEquals(PolicyDecision.Decision.DENY, d) + Assert.assertEquals("No matching rule", dec.reason) + + // testRulePrioTwo: labels "public", "filtered", "private" will trigger testRulePrioOne and + // testRulePrioTwo. Rule with higher prio wins. + from = ServiceNode("IAmMatchedByRuleThreeOnly", null, null) + to = ServiceNode("hdfs://IAmMatchedByBothRules", null, null) + envCtx = HashMap() + req = DecisionRequest(from, to, setOf("public", "unusedlabel", "private"), envCtx) + dec = pdp.requestDecision(req) + Assert.assertNotNull(dec) + d = dec.decision + Assert.assertEquals(PolicyDecision.Decision.DENY, d) + Assert.assertEquals("testRulePrioThree", dec.reason) + } + + /** + * Generates n random rules matching a target endpoint (given as regex). + * + * All rules will take an "allow" decision. + * + * @param n The number of rules to generate + * @return The rules as String + */ + private fun generateRules(n: Int): String { + val sb = StringBuilder() + for (i in 0 until n) { + val ruleName = "testRule$i" + val targetName = "testTarget$i" + val labelName = "label$i" + sb.append("rule(").append(ruleName).append(").\n") + sb.append("has_decision(").append(ruleName).append(", allow).\n") + sb.append("has_alternativedecision(").append(ruleName).append(", allow).\n") + sb.append("receives_label(").append(ruleName).append(").\n") + sb.append("has_target(").append(ruleName).append(", ").append(targetName).append(").\n") + sb.append("has_obligation(") + .append(ruleName) + .append(", testObligation") + .append(i) + .append(").\n") + sb.append("service(").append(targetName).append(").\n") + sb.append("has_endpoint(").append(targetName).append(", \".*\").\n") + sb.append("creates_label(") + .append(targetName) + .append(", ") + .append(labelName) + .append(").\n") + sb.append("removes_label(") + .append(targetName) + .append(", ") + .append(labelName) + .append(").\n") + } + return sb.toString() + } + + private fun generateLabels(n: Int): String { + val sb = StringBuilder() + sb.append(generateRules(50)) + for (i in 0 until n) { + sb.append("creates_label(testTarget1, labelX").append(i).append(").\n") + sb.append("removes_label(testTarget1, labelX").append(i).append(").\n") + } + return sb.toString() + } + + companion object { + // Solving Towers of Hanoi in only two lines. Prolog FTW! + private const val HANOI_THEORY = + ("move(1,X,Y,_) :- " + + "write('Move top disk from '), write(X), write(' to '), write(Y), nl. \n" + + "move(N,X,Y,Z) :- N>1, M is N-1, move(M,X,Z,Y), move(1,X,Y,_), move(M,Z,Y,X). ") + + // A random but syntactically correct policy. + private const val EXAMPLE_POLICY = + ("\n" + + "%%%%%%%% Rules %%%%%%%%%%%%\n" + + "rule(denyAll).\n" + + "rule_priority(denyAll, 0).\n" + + "has_decision(denyAll, drop).\n" + + "receives_label(denyAll).\n" + + "has_target(denyAll, serviceAll).\n" + + "\n" + + "rule(allowRule).\n" + + "rule_priority(allowRule, 1).\n" + + "has_decision(allowRule, allow).\n" + + "receives_label(allowRule).\n" + + "has_target(allowRule, hiveMqttBrokerService).\n" + + "has_target(allowRule, anonymizerService).\n" + + "has_target(allowRule, loggerService).\n" + + "has_target(allowRule, hadoopClustersService).\n" + + "has_target(allowRule, testQueueService).\n" + + "\n" + + "rule(deleteAfterOneMonth).\n" + + "rule_priority(deleteAfterOneMonth, 1).\n" + + "has_decision(deleteAfterOneMonth, allow).\n" + + "receives_label(deleteAfterOneMonth) :- label(private).\n" + + "has_target(deleteAfterOneMonth, service78096644).\n" + + "has_obligation(deleteAfterOneMonth, obl1709554620).\n" + + "% generated service\n" + + "service(service78096644).\n" + + "has_endpoint(service78096644, \"hdfs.*\").\n" + + "% generated obligation\n" + + "requires_prerequisite(obl1709554620, delete_after_days(30)).\n" + + "has_alternativedecision(obl1709554620, drop).\n" + + "\n" + + "rule(anotherRule).\n" + + "rule_priority(anotherRule, 1).\n" + + "has_target(anotherRule, testQueueService).\n" + + "receives_label(anotherRule) :- label(private).\n" + + "has_decision(anotherRule, drop).\n" + + "\n" + + "%%%%%%%%%%%% Services %%%%%%%%%%%%\n" + + "service(serviceAll).\n" + + "has_endpoint(serviceAll,'.*').\n" + + "\n" + + "service(hiveMqttBrokerService).\n" + + "creates_label(hiveMqttBrokerService, labelone).\n" + + "creates_label(hiveMqttBrokerService, private).\n" + + "removes_label(hiveMqttBrokerService, labeltwo).\n" + + "has_endpoint(hiveMqttBrokerService, \"^paho:.*?tcp://broker.hivemq.com:1883.*\").\n" + + "has_property(hiveMqttBrokerService, type, public).\n" + + "\n" + + "service(anonymizerService).\n" + + "has_endpoint(anonymizerService, \".*anonymizer.*\").\n" + + "has_property(anonymizerService, myProp, anonymize('surname', 'name')).\n" + + "\n" + + "service(loggerService).\n" + + "has_endpoint(loggerService, \"^log.*\").\n" + + "\n" + + "service(hadoopClustersService).\n" + + "has_endpoint(hadoopClustersService, \"^hdfs://.*\").\n" + + "has_capability(hadoopClustersService, deletion).\n" + + "has_property(hadoopClustersService, anonymizes, anonymize('surname', 'name')).\n" + + "\n" + + "service(testQueueService).\n" + + "has_endpoint(testQueueService, \"^amqp:.*?:test\").") + + // Policy with extended labels, i.e. "purpose(green)" + private const val EXTENDED_LABELS_POLICY = + ("" + + "%%%%%%%% Rules %%%%%%%%%%%%\n" + + "rule(denyAll).\n" + + "rule_priority(denyAll, 0).\n" + + "has_decision(denyAll, drop).\n" + + "receives_label(denyAll).\n" + + "has_target(denyAll, serviceAll).\n" + + "\n" + + "rule(demo).\n" + + "rule_priority(demo, 1).\n" + + "has_target(demo, service473016340).\n" + + "service(service473016340).\n" + + "has_endpoint(service473016340,\"(ahc|ahc-ws|cxf|cxfbean|cxfrs)://.*\").\n" + + "receives_label(demo) :- label(purpose(green)).\n" // Note that Prolog does not + // support + // nested predicates. + + + "has_decision(demo, allow).\n" + + "\n" + + "%%%%% Services %%%%%%%%%%%%\n" + + "service(serviceAll).\n" + + "has_endpoint(serviceAll,'.*').\n" + + "creates_label(serviceAll, purpose(green)).\n" + + "\n" + + "service(sanitizedata).\n" + + "has_endpoint(sanitizedata, \"^bean://SanitizerBean.*\").\n" + + "creates_label(sanitizedata, public).\n" + + "removes_label(sanitizedata, private).\n") + + // Route from LUCON paper with path searching logic + private const val VERIFIABLE_ROUTE = + ("%\n" + + "% (C) Julian Schütte, Fraunhofer AISEC, 2017\n" + + "%\n" + + "% Demonstration of model checking a message route against a usage control policy\n" + + "%\n" + + "% Message Route definition\n" + + "%\n" + + "% hiveMqttBroker \n" + + "% / \\ \n" + + "% logger anonymizer \n" + + "% \\ / \n" + + "% hadoopClusters \n" + + "% | \n" + + "% testQueue \n" + + "entrynode(hiveMqttBroker).\n" + + "stmt(hiveMqttBroker).\n" + + "has_action(hiveMqttBroker, \"paho:something:tcp://broker.hivemq.com:1883/anywhere\").\n" + + "stmt(logger).\n" + + "has_action(logger, \"log\").\n" + + "stmt(anonymizer).\n" + + "has_action(anonymizer, \"hello_anonymizer_world\").\n" + + "stmt(hadoopClusters).\n" + + "has_action(hadoopClusters, \"hdfs://myCluser\").\n" + + "stmt(testQueue).\n" + + "has_action(testQueue, \"amqp:testQueue:test\").\n" + + "\n" + + "succ(hiveMqttBroker, logger).\n" + + "succ(hiveMqttBroker, anonymizer).\n" + + "succ(logger, hadoopClusters).\n" + + "succ(anonymizer, hadoopClusters).\n" + + "succ(hadoopClusters, testQueue).\n" + + "\n") + } +} diff --git a/ids-dataflow-control/src/test/resources/policy-example.pl b/ids-dataflow-control/src/test/resources/policy-example.pl index ecb09bcf4..401823dc6 100644 --- a/ids-dataflow-control/src/test/resources/policy-example.pl +++ b/ids-dataflow-control/src/test/resources/policy-example.pl @@ -19,7 +19,7 @@ %:- discontiguous has_alternativedecision/2. %:- discontiguous has_obligation/2. %:- discontiguous receives_label/1. -regex(A,B,C) :- class("java.util.regex.Pattern") <- matches(A,B) returns C. + %%%%%%%% Rules %%%%%%%%%%%% % I am a test rule of prio 3 rule(testRulePrioThree). diff --git a/ids-dynamic-tls/build.gradle b/ids-dynamic-tls/build.gradle deleted file mode 100644 index 6adc3de61..000000000 --- a/ids-dynamic-tls/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - osgiCore group: 'org.osgi', name: 'org.osgi.core', version: libraryVersions.osgi - - providedByFeature group: 'org.eclipse.jetty', name: 'jetty-util', version: libraryVersions.jetty -} diff --git a/ids-dynamic-tls/build.gradle.kts b/ids-dynamic-tls/build.gradle.kts new file mode 100644 index 000000000..e5e6bb3c5 --- /dev/null +++ b/ids-dynamic-tls/build.gradle.kts @@ -0,0 +1,10 @@ +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map + +dependencies { + providedByBundle(project(":ids-api")) { isTransitive = false } + + osgiCore("org.osgi", "org.osgi.core", libraryVersions["osgi"]) + + providedByFeature("org.eclipse.jetty", "jetty-util", libraryVersions["jetty"]) +} diff --git a/ids-endpoint-config/build.gradle b/ids-endpoint-config/build.gradle deleted file mode 100644 index 71739fb9e..000000000 --- a/ids-endpoint-config/build.gradle +++ /dev/null @@ -1,14 +0,0 @@ -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - osgiCore group: 'org.osgi', name: 'osgi.cmpn', version: libraryVersions.osgiCompendium - - testImplementation group: 'junit', name: 'junit' - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito -} - - - diff --git a/ids-endpoint-config/build.gradle.kts b/ids-endpoint-config/build.gradle.kts new file mode 100644 index 000000000..1799fe472 --- /dev/null +++ b/ids-endpoint-config/build.gradle.kts @@ -0,0 +1,11 @@ +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map + +dependencies { + providedByBundle(project(":ids-api")) { isTransitive = false } + + osgiCore("org.osgi", "osgi.cmpn", libraryVersions["osgiCompendium"]) + + testImplementation("junit", "junit", libraryVersions["junit4"]) + testImplementation("org.mockito", "mockito-core", libraryVersions["mockito"]) +} diff --git a/ids-infomodel-manager/bnd.bnd b/ids-infomodel-manager/bnd.bnd index eb5e35ef0..44ce5e1b2 100644 --- a/ids-infomodel-manager/bnd.bnd +++ b/ids-infomodel-manager/bnd.bnd @@ -1,12 +1,15 @@ Bundle-Name: IDS :: Information Model Manager Export-Package: \ + com.fasterxml.jackson.annotation,\ + com.github.jsonldjava*,\ de.fhg.aisec.ids.informationmodelmanager.deserializer,\ de.fraunhofer.iais.eis*;-split-package:=merge-last,\ org.eclipse.rdf4j*,\ - com.github.jsonldjava*,\ !org.apache.logging*,\ org.apache* Import-Package: \ + com.github.jsonldjava.shaded.com.google.common.util.concurrent.internal;resolution:=optional,\ + com.google.*;resolution:=optional,\ com.sun.jdmk.comm;resolution:=optional,\ com.sun.org.apache.xerces*;resolution:=optional,\ edu.sussex.nlp.jws;resolution:=optional,\ @@ -15,6 +18,7 @@ Import-Package: \ net.spy.memcached;resolution:=optional,\ org.apache.commons*;resolution:=optional,\ org.apache.log;resolution:=optional,\ + !org.checkerframework.checker*,\ org.eclipse*;resolution:=optional,\ org.slf4j.ext;resolution:=optional,\ org.zeromq;resolution:=optional,\ diff --git a/ids-infomodel-manager/build.gradle.kts b/ids-infomodel-manager/build.gradle.kts index 95e0afde7..65e5c4f76 100644 --- a/ids-infomodel-manager/build.gradle.kts +++ b/ids-infomodel-manager/build.gradle.kts @@ -1,14 +1,34 @@ -import org.yaml.snakeyaml.Yaml +import org.gradle.plugins.ide.idea.model.IdeaModel -dependencies { - @Suppress("UNCHECKED_CAST") val libraryVersions = - Yaml().load(File("${rootDir}/libraryVersions.yaml").inputStream()) as Map +plugins { + id("com.github.gmazzo.buildconfig") version "2.0.2" +} + +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map + +apply(plugin = "idea") + +buildConfig { + sourceSets.getByName("main") { + packageName("de.fhg.aisec.ids.informationmodelmanager") + buildConfigField("String", "INFOMODEL_VERSION", + "\"${libraryVersions["infomodel"] ?: error("Infomodel version not available")}\"") + } +} + +configure { + module { + // mark as generated sources for IDEA + generatedSourceDirs.add(File("${buildDir}/generated/source/buildConfig/main/main")) + } +} +dependencies { infomodelBundle(project(":ids-api")) { isTransitive = false } - // MVN resolution problem workaround for infomodel until publicly released implementation("de.fraunhofer.iais.eis.ids.infomodel", "java", libraryVersions["infomodel"]) - implementation("de.fraunhofer.iais.eis.ids", "infomodel-serializer", libraryVersions["infomodelSerializer"]) + implementation("de.fraunhofer.iais.eis.ids", "infomodel-serializer", libraryVersions["infomodel"]) infomodelBundle("commons-cli", "commons-cli", libraryVersions["commonsCli"]) @@ -18,7 +38,4 @@ dependencies { infomodelBundle("com.fasterxml.jackson.core", "jackson-databind", libraryVersions["jackson"]) osgiCore("org.osgi", "osgi.cmpn", libraryVersions["osgiCompendium"]) - - compileOnly("org.apache.logging.log4j", "log4j-core", libraryVersions["log4j"]) - compileOnly("org.apache.logging.log4j", "log4j-slf4j-impl", libraryVersions["log4j"]) } diff --git a/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/InfoModelService.kt b/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/InfoModelService.kt index c51fb8a15..004abd6e3 100644 --- a/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/InfoModelService.kt +++ b/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/InfoModelService.kt @@ -1,3 +1,22 @@ +/*- + * ========================LICENSE_START================================= + * ids-infomodel-manager + * %% + * Copyright (C) 2021 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ package de.fhg.aisec.ids.informationmodelmanager import de.fhg.aisec.ids.api.conm.ConnectionManager @@ -7,120 +26,133 @@ import de.fhg.aisec.ids.api.settings.Settings import de.fraunhofer.iais.eis.* import de.fraunhofer.iais.eis.ids.jsonld.Serializer import de.fraunhofer.iais.eis.util.ConstraintViolationException -import de.fraunhofer.iais.eis.util.PlainLiteral -import de.fraunhofer.iais.eis.util.Util +import de.fraunhofer.iais.eis.util.TypedLiteral +import java.net.URI +import java.net.URISyntaxException +import java.util.* import org.osgi.service.component.annotations.Component import org.osgi.service.component.annotations.Reference import org.osgi.service.component.annotations.ReferenceCardinality import org.slf4j.LoggerFactory -import java.net.URI -import java.net.URISyntaxException -import java.util.* - -/** - * IDS Info Model Manager. - */ +/** IDS Info Model Manager. */ @Component(name = "ids-infomodel-manager", immediate = true) class InfoModelService : InfoModel { - @Reference(cardinality = ReferenceCardinality.MANDATORY) - private var settings: Settings? = null + @Reference(cardinality = ReferenceCardinality.MANDATORY) private lateinit var settings: Settings @Reference(cardinality = ReferenceCardinality.OPTIONAL) private var connectionManager: ConnectionManager? = null - private val connectorProfile: ConnectorProfile? - get() = settings?.connectorProfile + private val connectorProfile: ConnectorProfile + get() = settings.connectorProfile - /** - * Build Connector Entity Names from preferences - */ - private val connectorEntityNames: List - get() = connectorProfile?.connectorEntityNames.also { - if (it == null) { - LOG.warn("Settings or ConnectorProfile not available, or no connector entity names provided") + override val modelVersion = BuildConfig.INFOMODEL_VERSION + + /** Build Connector Entity Names from preferences */ + private val connectorEntityNames: List + get() = + connectorProfile.connectorEntityNames.also { + if (it == null) { + LOG.warn( + "Settings or ConnectorProfile not available, or no connector entity names provided" + ) + } } - } ?: emptyList() + ?: emptyList() - private val catalog: Catalog - get() = CatalogBuilder()._offer_(ArrayList(resources)).build() + private val catalog: ArrayList + get() = + arrayListOf(ResourceCatalogBuilder()._offeredResource_(ArrayList(resources)).build()) /** - * Build current endpoints as given by connectionManager - * will not be stored in preferences, but freshly loaded each time. - * Multiple names for one connector allowed + * Build current endpoints as given by connectionManager will not be stored in preferences, but + * freshly loaded each time. Multiple names for one connector allowed */ private val resources: List - get() = connectionManager?.let { cm -> - cm.listAvailableEndpoints().map { - val url = URI.create("${it.defaultProtocol}://${it.host}:${it.port}") - val host = HostBuilder()._accessUrl_(url)._protocol_(Protocol.IDSCP).build() - val endpoint = StaticEndpointBuilder()._endpointHost_(host).build() - ResourceBuilder()._resourceEndpoint_(arrayListOf(endpoint)).build() + get() = + connectionManager?.let { cm -> + cm.listAvailableEndpoints().map { + val url = URI.create("${it.defaultProtocol}://${it.host}:${it.port}") + val endpoint = ConnectorEndpointBuilder()._accessURL_(url).build() + ResourceBuilder()._resourceEndpoint_(arrayListOf(endpoint)).build() + } } - } ?: emptyList() + ?: emptyList() /** - * Build Security Profile from preferences - * defaults to "NONE" for all attributes in case nothing has been stored + * Build Security Profile from preferences defaults to "NONE" for all attributes in case nothing + * has been stored * @return */ private val securityProfile: SecurityProfile? - get() = connectorProfile?.securityProfile.also { - if (it == null) { - LOG.warn("Settings, ConnectorProfile not available, or no SecurityProfile provided") + get() = + connectorProfile.securityProfile.also { + if (it == null) { + LOG.warn( + "Settings, ConnectorProfile not available, or no SecurityProfile provided" + ) + } } - } - // creates and returns Connector object based on stored preferences - // returns random connector_url if none is stored in preferences - // op_url and entityNames can not be null - override fun getConnector(): Connector? { - val maintainerUrl = connectorProfile?.maintainerUrl - val connectorUrl = connectorProfile?.connectorUrl - val entityNames = connectorEntityNames - - if (LOG.isTraceEnabled) { - LOG.trace("Maintainer URL: {}, Connector URL: {}, Entity Names: {}", - maintainerUrl, connectorUrl, entityNames) - } + /** + * Creates and returns Connector object based on stored preferences. Returns random + * connector_url if none is stored in preferences. The fields op_url and entityNames cannot be + * null. + */ + override val connector: Connector? + get() { + val maintainerUrl = connectorProfile.maintainerUrl + val connectorUrl = connectorProfile.connectorUrl + val entityNames = connectorEntityNames + + if (LOG.isTraceEnabled) { + LOG.trace( + "Maintainer URL: {}, Connector URL: {}, Entity Names: {}", + maintainerUrl, + connectorUrl, + entityNames + ) + } - if (maintainerUrl != null) { - try { - val trustedConnectorBuilder = if (connectorUrl == null) { - TrustedConnectorBuilder() - } else { - TrustedConnectorBuilder(connectorUrl) - ._host_(Util.asList(HostBuilder() - ._accessUrl_(connectorUrl).build())) - } - trustedConnectorBuilder._maintainer_(maintainerUrl) - return trustedConnectorBuilder._title_(ArrayList(entityNames)) + return if (maintainerUrl != null) { + try { + val trustedConnectorBuilder = + if (connectorUrl == null) { + TrustedConnectorBuilder() + } else { + TrustedConnectorBuilder(connectorUrl) + } + trustedConnectorBuilder + ._maintainer_(maintainerUrl) + ._title_(ArrayList(entityNames)) ._securityProfile_(securityProfile) - ._catalog_(catalog) - ._description_(ArrayList(entityNames)).build() - } catch (ex: ConstraintViolationException) { - LOG.error("Caught ConstraintViolationException while building Connector", ex) - return null - } catch (ex: URISyntaxException) { - LOG.error("Caught URISyntaxException while building Connector", ex) - return null + ._resourceCatalog_(catalog) + ._description_(ArrayList(entityNames)) + .build() + } catch (ex: ConstraintViolationException) { + LOG.error("Caught ConstraintViolationException while building Connector", ex) + null + } catch (ex: URISyntaxException) { + LOG.error("Caught URISyntaxException while building Connector", ex) + null + } + } else { + LOG.warn("Connector couldn't be built: Maintainer URL is required!") + null } - } else { - LOG.warn("Connector couldn't be built: Maintainer URL is required!") - return null } - } - // store or update new Connector description to preferences - // creates random connector_url if null and succeeds only if maintainerUrl and entityNames != null - // generates RDF description from Connector object and returns building success + /** + * Store or update new Connector description to preferences. Creates random connector_url if + * null and succeeds only if maintainerUrl and entityNames != null Generates RDF description + * from Connector object and returns building success + */ override fun setConnector(profile: ConnectorProfile): Boolean { if (profile.securityProfile == null) { - profile.securityProfile = SecurityProfile.BASE_CONNECTOR_SECURITY_PROFILE + profile.securityProfile = SecurityProfile.TRUST_SECURITY_PROFILE } - return if (settings != null) { - settings?.connectorProfile = profile + return run { + settings.connectorProfile = profile try { connector != null @@ -128,18 +160,17 @@ class InfoModelService : InfoModel { LOG.error("ConstraintViolationException while building Connector.", ex) false } - } else { - LOG.warn("Couldn't store connector object: Settings not available.") - false } } - override fun getConnectorAsJsonLd(): String = settings?.connectorJsonLd - ?: connector?.let { serializer.serialize(it) } - ?: throw NullPointerException("Connector is not available") + override val connectorAsJsonLd: String + get() = + settings.connectorJsonLd + ?: connector?.let { serializer.serialize(it) } + ?: throw NullPointerException("Connector is not available") override fun setConnectorByJsonLd(jsonLd: String?) { - settings?.let { settings -> + settings.let { settings -> if (jsonLd != null) { try { serializer.deserialize(jsonLd, TrustedConnector::class.java) @@ -149,24 +180,11 @@ class InfoModelService : InfoModel { } } settings.connectorJsonLd = jsonLd - } ?: LOG.warn("Couldn't store connector object: Settings not available.") + } } - override fun getDynamicAttributeToken(): String = settings?.dynamicAttributeToken - ?: throw NullPointerException("DAPS token is not available") - - override fun setDynamicAttributeToken(dynamicAttributeToken: String) = - if (settings != null) { - settings?.dynamicAttributeToken = dynamicAttributeToken - true - } else { - LOG.warn("Couldn't store connector object: Settings not available.") - false - } - companion object { private val LOG = LoggerFactory.getLogger(InfoModelService::class.java) private val serializer: Serializer by lazy { Serializer() } } - } diff --git a/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/deserializer/CustomModule.kt b/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/deserializer/CustomModule.kt index 2d4a1dc67..65853c0db 100644 --- a/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/deserializer/CustomModule.kt +++ b/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/deserializer/CustomModule.kt @@ -1,15 +1,15 @@ /*- * ========================LICENSE_START================================= - * IDS Core Platform Webconsole + * ids-infomodel-manager * %% * Copyright (C) 2017 - 2018 Fraunhofer AISEC * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,12 +21,10 @@ package de.fhg.aisec.ids.informationmodelmanager.deserializer import com.fasterxml.jackson.databind.module.SimpleModule -import de.fraunhofer.iais.eis.SecurityProfile - // allows Jackson to deserialize custom object types class CustomModule : SimpleModule("CustomModule") { init { -// this.addDeserializer(SecurityProfile::class.java, SecurityProfileDeserializer()) + // this.addDeserializer(SecurityProfile::class.java, SecurityProfileDeserializer()) } companion object { diff --git a/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/deserializer/CustomObjectMapper.kt b/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/deserializer/CustomObjectMapper.kt index e2a9f4d91..c354bab82 100644 --- a/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/deserializer/CustomObjectMapper.kt +++ b/ids-infomodel-manager/src/main/kotlin/de/fhg/aisec/ids/informationmodelmanager/deserializer/CustomObjectMapper.kt @@ -1,6 +1,6 @@ /*- * ========================LICENSE_START================================= - * IDS Core Platform Webconsole + * ids-infomodel-manager * %% * Copyright (C) 2017 - 2018 Fraunhofer AISEC * %% diff --git a/ids-route-manager/build.gradle b/ids-route-manager/build.gradle deleted file mode 100644 index 5a7fbf5bf..000000000 --- a/ids-route-manager/build.gradle +++ /dev/null @@ -1,21 +0,0 @@ -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - - // Bill of Materials (BOM) for Camel - bom group: 'org.apache.camel', name: 'camel-parent', version: libraryVersions.camel - - providedByFeature group: 'org.apache.camel', name: 'camel-core', version: libraryVersions.camel - providedByFeature group: 'org.apache.camel', name: 'camel-management', version: libraryVersions.camel - - compileOnly group: 'org.checkerframework', name: 'checker-qual', version: libraryVersions.checkerQual - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - osgiCore group: 'org.apache.felix', name: 'org.apache.felix.framework', version: libraryVersions.felixFramework - osgiCore group: 'org.osgi', name: 'osgi.cmpn', version: libraryVersions.osgiCompendium - - testImplementation group: 'junit', name: 'junit' - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito - testImplementation group: 'org.apache.camel', name: 'camel-test', version: libraryVersions.camel -} diff --git a/ids-route-manager/build.gradle.kts b/ids-route-manager/build.gradle.kts new file mode 100644 index 000000000..9a7aad96d --- /dev/null +++ b/ids-route-manager/build.gradle.kts @@ -0,0 +1,25 @@ +dependencies { + @Suppress("UNCHECKED_CAST") val libraryVersions = + rootProject.extra.get("libraryVersions") as Map + + providedByBundle(project(":ids-api")) { isTransitive = false } + + implementation("de.fraunhofer.iais.eis.ids.infomodel", "java", libraryVersions["infomodel"]) + + providedByFeature("javax.xml.bind", "jaxb-api", libraryVersions["jaxbApi"]) + providedByFeature("org.apache.camel", "camel-core", libraryVersions["camel"]) + providedByFeature("org.apache.camel", "camel-management", libraryVersions["camel"]) + + osgiCore("org.apache.felix", "org.apache.felix.framework", libraryVersions["felixFramework"]) + osgiCore("org.osgi", "osgi.cmpn", libraryVersions["osgiCompendium"]) + + providedByBundle("com.google.guava", "guava", libraryVersions["guava"]) + + testImplementation("com.sun.xml.bind", "jaxb-core", libraryVersions["jaxbCore"]) + testImplementation("com.sun.xml.bind", "jaxb-impl", libraryVersions["jaxbImpl"]) + testImplementation("com.sun.activation", "javax.activation", libraryVersions["jaxActivation"]) + + testImplementation("junit", "junit", libraryVersions["junit4"]) + testImplementation("org.mockito", "mockito-core", libraryVersions["mockito"]) + testImplementation("org.apache.camel", "camel-test", libraryVersions["camel"]) +} diff --git a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/CamelInterceptor.java b/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/CamelInterceptor.java deleted file mode 100644 index 3729f1374..000000000 --- a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/CamelInterceptor.java +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-route-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.rm; - -import org.apache.camel.CamelContext; -import org.apache.camel.NamedNode; -import org.apache.camel.Processor; -import org.apache.camel.spi.InterceptStrategy; -import org.checkerframework.checker.nullness.qual.NonNull; - -public class CamelInterceptor implements InterceptStrategy { - private RouteManagerService rm; - - CamelInterceptor(@NonNull RouteManagerService rm) { - this.rm = rm; - } - - @Override - public Processor wrapProcessorInInterceptors( - final CamelContext context, - final NamedNode node, - final Processor target, - final Processor nextTarget) { - return new PolicyEnforcementPoint(context, node, target, this.rm); - } -} diff --git a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/PolicyEnforcementPoint.java b/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/PolicyEnforcementPoint.java deleted file mode 100644 index 10690ff07..000000000 --- a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/PolicyEnforcementPoint.java +++ /dev/null @@ -1,181 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-route-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.rm; - -import de.fhg.aisec.ids.api.policy.*; -import org.apache.camel.*; -import org.apache.camel.model.RouteDefinition; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.CompletableFuture; - -public class PolicyEnforcementPoint implements AsyncProcessor { - private static final Logger LOG = LoggerFactory.getLogger(PolicyEnforcementPoint.class); - private CamelContext ctx; - private NamedNode node; - private Processor target; - private RouteManagerService rm; - - PolicyEnforcementPoint( - @NonNull CamelContext ctx, - @NonNull NamedNode node, - @NonNull Processor target, - @NonNull RouteManagerService rm) { - this.ctx = ctx; - this.node = node; - this.target = target; - this.rm = rm; - } - - /** - * The method performs flow control and calls Exchange.setException() when necessary - * - * @param exchange The exchange object to check - * @return Whether target.process() is to be called for this exchange object - */ - private boolean processFlowControl(Exchange exchange) { - if (exchange == null) { - if (LOG.isWarnEnabled()) { - LOG.warn("Cannot check data flow policy. Exchange object is null."); - } - return false; - } - - if (target == null) { - if (LOG.isWarnEnabled()) { - LOG.warn("Cannot check data flow policy. The target is null."); - } - return false; - } - - // Strict policy: If no PDP is available, block every checked data flow - if (rm == null) { - LOG.error("RouteManager is not available, aborting..."); - return false; - } - PDP pdp = rm.getPdp(); - if (pdp == null) { - LOG.error("PDP is not available, aborting..."); - return false; - } - - String source = (String) exchange.getProperty("lastDestination"); - if (source == null) { - var routeNode = node.getParent(); - while (!(routeNode instanceof RouteDefinition)) { - routeNode = node.getParent(); - } - source = ((RouteDefinition) routeNode).getInput().toString(); - } - String destination = node.toString(); - exchange.setProperty("lastDestination", destination); - - if (LOG.isTraceEnabled()) { - LOG.trace("{} -> {}", source, destination); - } - - /* - * TODO: - * Nodes currently have no properties or capabilities. They should be retrieved from - * a) either the prolog knowledge base (a respective query must be created) - * b) or from service meta data provided by the ConnectionManagerService(?) - */ - ServiceNode sourceNode = new ServiceNode(source, null, null); - ServiceNode destNode = new ServiceNode(destination, null, null); - - // Call PDP to transform labels and decide whether to forward the Exchange - applyLabelTransformation(pdp.requestTranformations(sourceNode), exchange); - PolicyDecision decision = - pdp.requestDecision( - new DecisionRequest(sourceNode, destNode, exchange.getProperties(), null)); - - switch (decision.getDecision()) { - case ALLOW: - // forward the Exchange - return true; - case DENY: - default: - if (LOG.isWarnEnabled()) { - LOG.warn( - "Exchange blocked by data flow policy. Source: {}, Target: {}", sourceNode, destNode); - } - exchange.setException(new Exception("Exchange blocked by data flow policy")); - return false; - } - - // TODO: Obligation Implementation - } - - /** - * Removes and adds labels to an exchange object. - * - * @param requestTransformations The request transformations (label changes) to be performed - * @param exchange Exchange processed - */ - @SuppressWarnings("unchecked") - private void applyLabelTransformation( - TransformationDecision requestTransformations, Exchange exchange) { - Set labels = - (Set) - exchange.getProperties().computeIfAbsent(PDP.LABELS_KEY, k -> new HashSet()); - - // Remove labels from exchange - labels.removeAll(requestTransformations.getLabelsToRemove()); - - // Add labels to exchange - labels.addAll(requestTransformations.getLabelsToAdd()); - } - - @Override - public void process(Exchange exchange) throws Exception { - if (processFlowControl(exchange)) { - target.process(exchange); - } - } - - @Override - public boolean process(Exchange exchange, AsyncCallback callback) { - if (processFlowControl(exchange)) { - try { - target.process(exchange); - callback.done(true); - return true; - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } - } - callback.done(false); - return false; - } - - @Override - public CompletableFuture processAsync(Exchange exchange) { - try { - target.process(exchange); - return CompletableFuture.completedFuture(exchange); - } catch (Exception x) { - return CompletableFuture.failedFuture(x); - } - } -} diff --git a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/RouteManagerService.java b/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/RouteManagerService.java deleted file mode 100644 index 224c4aed6..000000000 --- a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/RouteManagerService.java +++ /dev/null @@ -1,567 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-route-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.rm; - -import de.fhg.aisec.ids.api.ReferenceUnbind; -import de.fhg.aisec.ids.api.policy.PDP; -import de.fhg.aisec.ids.api.router.*; -import de.fhg.aisec.ids.rm.util.CamelRouteToDot; -import de.fhg.aisec.ids.rm.util.PrologPrinter; -import org.apache.camel.*; -import org.apache.camel.impl.DefaultCamelContext; -import org.apache.camel.management.DefaultManagementAgent; -import org.apache.camel.model.*; -import org.apache.camel.spi.ManagementAgent; -import org.apache.camel.support.dump.RouteStatDump; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; -import org.osgi.service.component.ComponentContext; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.management.*; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.Map.Entry; -import java.util.stream.Collectors; - -/** - * Manages Camel routes. - * - * @author Julian Schuette (julian.schuette@aisec.fraunhofer.de) - */ -@Component(immediate = true, name = "ids-routemanager") -public class RouteManagerService implements RouteManager { - private static final Logger LOG = LoggerFactory.getLogger(RouteManagerService.class); - - @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC) - private volatile PDP pdp; - - private ComponentContext ctx; - - @Activate - protected void activate(ComponentContext ctx) { - this.ctx = ctx; - } - - @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) - public void bindCamelContext(CamelContext cCtx) { - try { - cCtx.stop(); - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } - CamelInterceptor interceptor = new CamelInterceptor(this); - var routeController = cCtx.getRouteController(); - var ecc = cCtx.adapt(ExtendedCamelContext.class); - ecc.addInterceptStrategy(interceptor); - for (Route r : cCtx.getRoutes()) { - try { - routeController.stopRoute(r.getId()); - routeController.startRoute(r.getId()); - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } - } - try { - cCtx.start(); - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } - } - - @ReferenceUnbind - public void unbindCamelContext(CamelContext cCtx) { - if (LOG.isDebugEnabled()) { - LOG.debug("Unbound from CamelContext " + cCtx); - } - } - - PDP getPdp() { - return pdp; - } - - @Override - @NonNull - public List getRoutes() { - List result = new ArrayList<>(); - List camelContexts = getCamelContexts(); - - // Create response - for (CamelContext cCtx : camelContexts) { - var mcc = cCtx.adapt(ModelCamelContext.class); - for (RouteDefinition rd : mcc.getRouteDefinitions()) { - result.add(routeDefinitionToObject(cCtx, rd)); - } - } - return result; - } - - @Override - public RouteObject getRoute(@NonNull String id) { - List camelContexts = getCamelContexts(); - - // Create response - for (CamelContext cCtx : camelContexts) { - var mcc = cCtx.adapt(ModelCamelContext.class); - RouteDefinition rd = mcc.getRouteDefinition(id); - if (rd != null) { - return routeDefinitionToObject(cCtx, rd); - } - } - - return null; - } - - @Override - public void startRoute(@Nullable String routeId) throws RouteException { - List camelC = getCamelContexts(); - - for (CamelContext cCtx : camelC) { - Route rt = cCtx.getRoute(routeId); - if (rt != null) { - try { - cCtx.getRouteController().startRoute(routeId); - } catch (Exception e) { - throw new RouteException(e); - } - } - } - } - - @Override - public void stopRoute(@Nullable String routeId) throws RouteException { - List camelC = getCamelContexts(); - - for (CamelContext cCtx : camelC) { - Route rt = cCtx.getRoute(routeId); - if (rt != null) { - try { - cCtx.getRouteController().stopRoute(routeId); - } catch (Exception e) { - throw new RouteException(e); - } - } - } - } - - @Override - @NonNull - public List listComponents() { - List componentNames = new ArrayList<>(); - BundleContext bCtx = FrameworkUtil.getBundle(RouteManagerService.class).getBundleContext(); - if (bCtx == null) { - return componentNames; - } - - try { - ServiceReference[] services = - bCtx.getServiceReferences("org.apache.camel.spi.ComponentResolver", null); - for (ServiceReference sr : services) { - String bundle = sr.getBundle().getHeaders().get("Bundle-Name"); - if (bundle == null || "".equals(bundle)) { - bundle = sr.getBundle().getSymbolicName(); - } - String description = sr.getBundle().getHeaders().get("Bundle-Description"); - if (description == null) { - description = ""; - } - componentNames.add(new RouteComponent(bundle, description)); - } - } catch (InvalidSyntaxException e) { - LOG.error(e.getMessage(), e); - } - return componentNames; - } - - @Override - @NonNull - public Map> getEndpoints() { - List camelO = getCamelContexts(); - return camelO - .stream() - .collect( - Collectors.toMap( - CamelContext::getName, - c -> - c.getEndpoints() - .stream() - .map(Endpoint::getEndpointUri) - .collect(Collectors.toList()))); - } - - @Override - @NonNull - public Map listEndpoints() { - Map epURIs = new HashMap<>(); - - for (CamelContext cCtx : getCamelContexts()) { - for (Entry, Endpoint> e : cCtx.getEndpointRegistry().entrySet()) { - epURIs.put(e.getKey().get(), e.getValue().getEndpointUri()); - } - } - - return epURIs; - } - - @Override - @NonNull - public Map getRouteMetrics() { - Map rdump = new HashMap<>(); - List cCtxs = getCamelContexts(); - for (CamelContext cCtx : cCtxs) { - var mcc = cCtx.adapt(ModelCamelContext.class); - List rds = mcc.getRouteDefinitions(); - for (RouteDefinition rd : rds) { - RouteStatDump stat; - try { - stat = this.getRouteStats(cCtx, rd); - if (stat != null) { - RouteMetrics m = new RouteMetrics(); - m.setCompleted(stat.getExchangesCompleted()); - m.setRedeliveries(stat.getRedeliveries()); - m.setFailed(stat.getExchangesFailed()); - m.setFailuresHandled(stat.getFailuresHandled()); - m.setInflight(stat.getExchangesInflight()); - m.setMaxProcessingTime(stat.getMaxProcessingTime()); - m.setMinProcessingTime(stat.getMinProcessingTime()); - m.setMeanProcessingTime(stat.getMeanProcessingTime()); - rdump.put(rd.getId(), m); - } - } catch (MalformedObjectNameException - | AttributeNotFoundException - | InstanceNotFoundException - | MBeanException - | ReflectionException - | JAXBException e) { - LOG.error(e.getMessage(), e); - } - } - } - return rdump; - } - - @Override - public void delRoute(@Nullable String routeId) { - List cCtxs = getCamelContexts(); - for (CamelContext cCtx : cCtxs) { - var mcc = cCtx.adapt(ModelCamelContext.class); - for (RouteDefinition rd : mcc.getRouteDefinitions()) { - if (rd.getId().equals(routeId)) { - try { - cCtx.removeRoute(rd.getId()); - } catch (Exception e) { - LOG.error(e.getMessage(), e); - } - return; - } - } - } - } - - @NonNull - private List getCamelContexts() { - List camelContexts = new ArrayList<>(); - try { - ServiceReference[] references = - this.ctx.getBundleContext().getServiceReferences(CamelContext.class.getName(), null); - if (references != null) { - Arrays.stream(references) - .map(this.ctx.getBundleContext()::getService) - .filter(Objects::nonNull) - .map(CamelContext.class::cast) - .forEach(camelContexts::add); - } - } catch (Exception e) { - LOG.warn("Cannot retrieve the list of Camel contexts.", e); - } - - // sort the list - camelContexts.sort(Comparator.comparing(CamelContext::getName)); - return camelContexts; - } - - /** - * Wraps a RouteDefinition in a RouteObject for use over API. - * - * @param cCtx Camel Context - * @param rd The RouteDefinition to be transformed - * @return The resulting RouteObject - */ - private RouteObject routeDefinitionToObject( - @NonNull CamelContext cCtx, @NonNull RouteDefinition rd) { - return new RouteObject( - rd.getId(), - rd.getDescriptionText(), - routeToDot(rd), - rd.getShortName(), - cCtx.getName(), - cCtx.getUptimeMillis(), - cCtx.getRouteController().getRouteStatus(rd.getId()).toString()); - } - - /** - * Creates a visualization of a Camel route in DOT (graphviz) format. - * - * @param rd The route definition to process - * @return The string representation of the Camel route in DOT - */ - @NonNull - private String routeToDot(@NonNull RouteDefinition rd) { - String result = ""; - try { - CamelRouteToDot viz = new CamelRouteToDot(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - BufferedWriter writer = - new BufferedWriter(new OutputStreamWriter(bos, StandardCharsets.UTF_8)); - viz.printSingleRoute(writer, rd); - writer.flush(); - result = bos.toString(StandardCharsets.UTF_8); - } catch (IOException e) { - LOG.error(e.getMessage(), e); - } - return result; - } - - @Override - @NonNull - public List getRouteInputUris(@NonNull String routeId) { - for (CamelContext ctx : getCamelContexts()) { - var mcc = ctx.adapt(ModelCamelContext.class); - for (RouteDefinition rd : mcc.getRouteDefinitions()) { - if (routeId.equals(rd.getId())) { - return Collections.singletonList(rd.getInput().getUri()); - } - } - } - return Collections.emptyList(); - } - - protected RouteStatDump getRouteStats(CamelContext cCtx, RouteDefinition rd) - throws MalformedObjectNameException, JAXBException, AttributeNotFoundException, - InstanceNotFoundException, MBeanException, ReflectionException { - JAXBContext context = JAXBContext.newInstance(RouteStatDump.class); - Unmarshaller unmarshaller = context.createUnmarshaller(); - ManagementAgent agent = cCtx.getManagementStrategy().getManagementAgent(); - if (agent != null) { - MBeanServer mBeanServer = agent.getMBeanServer(); - Set set = - mBeanServer.queryNames( - new ObjectName( - DefaultManagementAgent.DEFAULT_DOMAIN - + ":type=routes,name=\"" - + rd.getId() - + "\",*"), - null); - for (ObjectName routeMBean : set) { - // the route must be part of the camel context - String camelId = (String) mBeanServer.getAttribute(routeMBean, "CamelId"); - if (camelId != null && camelId.equals(cCtx.getName())) { - String xml = - (String) - mBeanServer.invoke( - routeMBean, - "dumpRouteStatsAsXml", - new Object[] {Boolean.FALSE, Boolean.TRUE}, - new String[] {"boolean", "boolean"}); - return (RouteStatDump) unmarshaller.unmarshal(new StringReader(xml)); - } - } - } - return null; - } - - /** - * Retrieves the Prolog representation of a route - * - * @param routeId The id of the route that is to be exported - */ - @Override - @NonNull - public String getRouteAsProlog(@NonNull String routeId) { - Optional c = - getCamelContexts() - .parallelStream() - .filter(cCtx -> cCtx.adapt(ModelCamelContext.class).getRouteDefinition(routeId) != null) - .findAny(); - - if (c.isPresent()) { - try { - RouteDefinition rd = c.get().adapt(ModelCamelContext.class).getRouteDefinition(routeId); - StringWriter writer = new StringWriter(); - new PrologPrinter().printSingleRoute(writer, rd); - writer.flush(); - return writer.toString(); - } catch (IOException e) { - LOG.error("Error printing route to prolog " + routeId, e); - } - } - - return ""; - } - - /** - * Retrieves the textual representation of a route - * - * @param routeId The id of the route that is to be exported - */ - @Override - @Nullable - public String getRouteAsString(@NonNull String routeId) { - for (CamelContext c : getCamelContexts()) { - RouteDefinition rd = c.adapt(ModelCamelContext.class).getRouteDefinition(routeId); - if (rd == null) { - continue; - } - try { - return ModelHelper.dumpModelAsXml(c, rd); - } catch (JAXBException e) { - LOG.error(e.getMessage(), e); - } - } - return null; - } - - /** - * Save a route, replacing it with a new representation within the same context - * - * @param routeId ID of the route to save - * @param routeRepresentation The new textual representation of the route (XML etc.) - * @throws RouteException If the route does not exist or some Exception was thrown during route - * replacement. - */ - @Override - @NonNull - public RouteObject saveRoute(@NonNull String routeId, @NonNull String routeRepresentation) - throws RouteException { - LOG.debug("Save route \"" + routeId + "\": " + routeRepresentation); - - CamelContext cCtx = null; - boolean routeStarted = false; - - // Find the state and CamelContext of the route to be saved - for (CamelContext c : getCamelContexts()) { - Route targetRoute = c.getRoute(routeId); - if (targetRoute != null) { - cCtx = c; - ServiceStatus serviceStatus = cCtx.getRouteController().getRouteStatus(routeId); - routeStarted = - serviceStatus == ServiceStatus.Started || serviceStatus == ServiceStatus.Starting; - break; - } - } - if (cCtx == null) { - LOG.error("Could not find route with id \"" + routeId + "\""); - throw new RouteException("Could not find route with id \"" + routeId + "\""); - } - - // Check for validity of route representation - List routes; - try (ByteArrayInputStream bis = - new ByteArrayInputStream(routeRepresentation.getBytes(StandardCharsets.UTF_8))) { - // Load route(s) from XML - RoutesDefinition rd = ModelHelper.loadRoutesDefinition(cCtx, bis); - routes = rd.getRoutes(); - Optional id = - routes.stream().map(RouteDefinition::getId).filter(rid -> !routeId.equals(rid)).findAny(); - if (id.isPresent()) { - throw new Exception( - "The new route representation has a different ID: " - + "Expected \"" - + routeId - + "\" but got \"" - + id.get() - + "\""); - } - } catch (Exception e) { - LOG.error(e.getMessage(), e); - throw new RouteException(e); - } - - // Remove old route from CamelContext - try { - cCtx.removeRoute(routeId); - } catch (Exception e) { - LOG.error("Error while removing old route \"" + routeId + "\"", e); - throw new RouteException(e); - } - - // Add new route and start it if it was started/starting before save - try { - RouteDefinition routeDefinition = routes.get(0); - cCtx.adapt(ModelCamelContext.class).addRouteDefinition(routeDefinition); - if (routeStarted) { - cCtx.getRouteController().startRoute(routeDefinition.getId()); - } - return routeDefinitionToObject(cCtx, routeDefinition); - } catch (Exception e) { - LOG.error("Error while adding new route \"" + routeId + "\"", e); - throw new RouteException(e); - } - } - - /** - * Create a new route in a fresh context from text - * - * @param routeRepresentation The textual representation of the route to be inserted - * @throws RouteException If a route with that name already exists - */ - @Override - public void addRoute(@NonNull String routeRepresentation) throws RouteException { - LOG.debug("Adding new route: " + routeRepresentation); - List existingRoutes = this.getRoutes(); - // @todo: Need to verify that this or the call to CamelContext.start() below actually registers - // the route properly - CamelContext cCtx = new DefaultCamelContext(); - try (ByteArrayInputStream bis = - new ByteArrayInputStream(routeRepresentation.getBytes(StandardCharsets.UTF_8))) { - // Load route(s) from XML - RoutesDefinition rd = ModelHelper.loadRoutesDefinition(cCtx, bis); - List routes = rd.getRoutes(); - // Check that intersection of existing and new routes is empty (=we do not allow overwriting - // existing route ids) - List intersect = - routes - .stream() - .filter(r -> existingRoutes.stream().anyMatch(er -> er.getId().equals(r.getId()))) - .map(OptionalIdentifiedDefinition::getId) - .collect(Collectors.toList()); - if (!intersect.isEmpty()) { - throw new RouteException( - "Route id already exists. Will not overwrite it. " + String.join(", ", intersect)); - } - cCtx.adapt(ModelCamelContext.class).addRouteDefinitions(routes); - cCtx.start(); - } catch (Exception e) { - LOG.error(e.getMessage(), e); - throw new RouteException(e); - } - } -} diff --git a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/CamelRouteToDot.java b/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/CamelRouteToDot.java deleted file mode 100644 index 1aed9addf..000000000 --- a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/CamelRouteToDot.java +++ /dev/null @@ -1,240 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-route-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.rm.util; - -import org.apache.camel.model.*; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.apache.camel.util.ObjectHelper.isNotEmpty; - -/** - * Camel route definition to GraphViz converter. - * - *

The output can be turned into pictures using dot, neato, and others. - */ -public class CamelRouteToDot { - protected final Map nodeMap = new IdentityHashMap<>(); - private int clusterCounter = 0; - private static final String PREFIX = "http://www.eaipatterns.com/img/"; - - protected void printRoutes(Writer writer, Map> map) - throws IOException { - Set>> entries = map.entrySet(); - for (Map.Entry> entry : entries) { - String group = entry.getKey(); - printRoutes(writer, group, entry.getValue()); - } - } - - protected void printRoutes(Writer writer, String group, List routes) - throws IOException { - if (group != null) { - writer.write("subgraph cluster_" + (clusterCounter++) + " {\n"); - writer.write("label = \"" + group + "\";\n"); - writer.write("color = grey;\n"); - writer.write("style = \"dashed\";\n"); - } - for (RouteDefinition route : routes) { - printRoute(writer, route, route.getInput()); - writer.write("\n"); - } - if (group != null) { - writer.write("}\n\n"); - } - } - - /** - * Prints graphviz code of a single RouteDefinition to the provided PrintWriter. - * - * @param writer - * @param route - * @throws IOException - */ - public void printSingleRoute(@Nullable Writer writer, @Nullable final RouteDefinition route) - throws IOException { - if (writer == null || route == null) { - return; - } - writer.write("digraph { rankdir=LR; size=\"4.5,5.5\" \n\n"); - writer.write( - "node [shape=\"box\", style = \"filled\", fillcolor = white, " - + "fontname=\"Helvetica-Oblique\"];"); - printRoute(writer, route, route.getInput()); - - writer.write("\n}"); - } - - protected void printRoute(Writer writer, final RouteDefinition route, FromDefinition input) - throws IOException { - NodeData nodeData = getNodeData(input); - - printNode(writer, nodeData); - - NodeData from = nodeData; - for (ProcessorDefinition output : route.getOutputs()) { - from = printNode(writer, from, output); - } - } - - protected NodeData printNode(Writer writer, NodeData fromData, ProcessorDefinition node) - throws IOException { - if (node instanceof MulticastDefinition) { - // no need for a multicast or interceptor node - List> outputs = node.getOutputs(); - boolean isPipeline = isPipeline(node); - for (ProcessorDefinition output : outputs) { - NodeData out = printNode(writer, fromData, output); - // if in pipeline then we should move the from node to the next - // in the pipeline - if (isPipeline) { - fromData = out; - } - } - return fromData; - } - NodeData toData = getNodeData(node); - - printNode(writer, toData); - - if (fromData != null) { - writer.write(fromData.id); - writer.write(" -> "); - writer.write(toData.id); - writer.write(" [\n"); - - String label = fromData.edgeLabel; - if (isNotEmpty(label)) { - writer.write("label = \"" + label + "\"\n"); - } - writer.write("];\n"); - } - - // now lets write any children - List> outputs = toData.outputs; - if (outputs != null) { - for (ProcessorDefinition output : outputs) { - NodeData newData = printNode(writer, toData, output); - if (!isMulticastNode(node)) { - toData = newData; - } - } - } - return toData; - } - - protected void printNode(Writer writer, NodeData data) throws IOException { - if (!data.nodeWritten) { - data.nodeWritten = true; - - writer.write("\n"); - writer.write(data.id + "\n"); - writer.write(" [\n"); - writer.write("label = \"" + data.label + "\"\n"); - writer.write("tooltip = \"" + data.tooltip + "\"\n"); - - String image = data.image; - if (image != null) { - writer.write("shapefile = \"" + image + "\"\n"); - writer.write("peripheries=0"); - } - String shape = data.shape; - if (shape == null && image != null) { - shape = "custom"; - } - if (shape != null) { - writer.write("shape = \"" + shape + "\"\n"); - } - writer.write("];\n\n"); - } - } - - public void generateFile( - @Nullable PrintWriter writer, @Nullable Map> map) - throws IOException { - if (writer == null || map == null) { - return; - } - writer.println("digraph CamelRoutes {"); - writer.println(); - - writer.println( - "node [style = \"rounded,filled\", fillcolor = white, color = \"#898989\", " - + "fontname=\"Helvetica-Oblique\"];"); - writer.println(); - printRoutes(writer, map); - - writer.println("}"); - } - - protected NodeData getNodeData(@NonNull Object node) { - Object key = node; - if (node instanceof FromDefinition) { - FromDefinition fromType = (FromDefinition) node; - key = fromType.getUri(); - } else if (node instanceof ToDefinition) { - ToDefinition toType = (ToDefinition) node; - key = toType.getUri(); - } - NodeData answer = null; - if (key != null) { - answer = nodeMap.get(key); - } - if (answer == null) { - String id = "node" + (nodeMap.size() + 1); - answer = new NodeData(id, node, PREFIX); - nodeMap.put(key, answer); - } - return answer; - } - - protected boolean isMulticastNode(ProcessorDefinition node) { - return node instanceof MulticastDefinition || node instanceof ChoiceDefinition; - } - - /** Is the given node a pipeline */ - protected boolean isPipeline(ProcessorDefinition node) { - if (node instanceof MulticastDefinition) { - return false; - } - if (node instanceof PipelineDefinition) { - return true; - } - if (node.getOutputs().size() > 1) { - // is pipeline if there is more than 1 output and they are all To - // types - for (Object type : node.getOutputs()) { - if (!(type instanceof ToDefinition)) { - return false; - } - } - return true; - } - return false; - } -} diff --git a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/GraphProcessor.java b/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/GraphProcessor.java deleted file mode 100644 index 17cfb8ef3..000000000 --- a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/GraphProcessor.java +++ /dev/null @@ -1,119 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-route-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.rm.util; - -import de.fhg.aisec.ids.api.router.graph.Edge; -import de.fhg.aisec.ids.api.router.graph.GraphData; -import de.fhg.aisec.ids.api.router.graph.Node; -import org.apache.camel.model.ChoiceDefinition; -import org.apache.camel.model.OptionalIdentifiedDefinition; -import org.apache.camel.model.ProcessorDefinition; -import org.apache.camel.model.RouteDefinition; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -public class GraphProcessor { - - /** - * Prints a single Camel route in Prolog representation. - * - * @param route The route to be transformed - */ - public static GraphData processRoute(RouteDefinition route) { - GraphData gd = new GraphData(); - // Print route entry points - processInput(gd, route); - return gd; - } - - /** - * Prints a single node of a Camel route in Prolog representation. - * - * @param graphData - * @param current - * @param preds - * @return - */ - private static List> processNode( - GraphData graphData, - ProcessorDefinition current, - List> preds) { - for (OptionalIdentifiedDefinition p : preds) { - graphData.addEdge(new Edge(p.getId(), current.getId())); - } - graphData.addNode( - new Node( - current.getId(), - current.getLabel(), - (current instanceof ChoiceDefinition) ? Node.NodeType.ChoiceNode : Node.NodeType.Node)); - - // predecessor of next recursion is the current node - List> newPreds = new ArrayList<>(); - newPreds.add(current); - for (ProcessorDefinition out : current.getOutputs()) { - // if this is a ChoiceDefinition, there is no link between its WhereDefinitions. - ArrayList> myPreds = new ArrayList<>(); - if (current instanceof ChoiceDefinition) { - myPreds.add(current); - } else { - // @TODO: Looks somewhat strange... is this correct? - myPreds.addAll(newPreds); - } - - // Recursion ... - List> p = processNode(graphData, out, myPreds); - - // Predecessors of a ChoiceDefinition are all last stmts of its Where- and - // OtherwiseDefinitions - if (current instanceof ChoiceDefinition) { - newPreds.addAll(p); - } else { - newPreds.clear(); - newPreds.addAll(p); - } - } - - return newPreds; - } - - /** - * Prints a single FromDefinition (= a route entry point) in Prolog representation. - */ - private static void processInput( - GraphData graphData, RouteDefinition route) { - AtomicInteger counter = new AtomicInteger(0); - var i = route.getInput(); - // Make sure every input node has a unique id - if (i.getId() == null) { - i.setCustomId(true); - i.setId("input" + counter); - } - graphData.addNode(new Node(i.getId(), i.getLabel(), Node.NodeType.EntryNode)); - - OptionalIdentifiedDefinition prev = i; - for (ProcessorDefinition next : route.getOutputs()) { - processNode(graphData, next, Collections.singletonList(prev)); - prev = next; - } - } -} diff --git a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/NodeData.java b/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/NodeData.java deleted file mode 100644 index 8df3a66ec..000000000 --- a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/NodeData.java +++ /dev/null @@ -1,196 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-route-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.rm.util; - -import static org.apache.camel.util.ObjectHelper.isEmpty; -import static org.apache.camel.util.ObjectHelper.isNotEmpty; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import org.apache.camel.model.AggregateDefinition; -import org.apache.camel.model.BeanDefinition; -import org.apache.camel.model.ChoiceDefinition; -import org.apache.camel.model.FilterDefinition; -import org.apache.camel.model.FromDefinition; -import org.apache.camel.model.OtherwiseDefinition; -import org.apache.camel.model.ProcessorDefinition; -import org.apache.camel.model.RecipientListDefinition; -import org.apache.camel.model.ResequenceDefinition; -import org.apache.camel.model.RoutingSlipDefinition; -import org.apache.camel.model.SplitDefinition; -import org.apache.camel.model.ToDefinition; -import org.apache.camel.model.TransformDefinition; -import org.apache.camel.model.WhenDefinition; - -/** Represents a node in Graphviz representation of a route. */ -public class NodeData { - public String id; - public String image; - public String label; - public String shape; - public String edgeLabel; - public String tooltip; - public String nodeType; - public boolean nodeWritten; - public String url; - public List> outputs; - - public NodeData(String id, Object node, String imagePrefix) { - this.id = id; - - if (node instanceof ProcessorDefinition) { - ProcessorDefinition processorType = (ProcessorDefinition) node; - this.edgeLabel = processorType.getLabel(); - } - if (node instanceof FromDefinition) { - FromDefinition fromType = (FromDefinition) node; - this.tooltip = fromType.getLabel(); - this.label = removeQueryString(this.tooltip); - this.url = "http://camel.apache.org/message-endpoint.html"; - } else if (node instanceof ToDefinition) { - ToDefinition toType = (ToDefinition) node; - this.tooltip = toType.getLabel(); - this.label = removeQueryString(this.tooltip); - this.edgeLabel = ""; - this.url = "http://camel.apache.org/message-endpoint.html"; - } else if (node instanceof FilterDefinition) { - this.image = imagePrefix + "MessageFilterIcon.png"; - this.label = "Filter"; - this.nodeType = "Message Filter"; - } else if (node instanceof WhenDefinition) { - this.image = imagePrefix + "MessageFilterIcon.png"; - this.nodeType = "When Filter"; - this.label = "When"; - this.url = "http://camel.apache.org/content-based-router.html"; - } else if (node instanceof OtherwiseDefinition) { - this.nodeType = "Otherwise"; - this.edgeLabel = ""; - this.url = "http://camel.apache.org/content-based-router.html"; - this.tooltip = "Otherwise"; - } else if (node instanceof ChoiceDefinition) { - this.image = imagePrefix + "ContentBasedRouterIcon.png"; - this.nodeType = "Content Based Router"; - this.label = "Choice"; - this.edgeLabel = ""; - - ChoiceDefinition choice = (ChoiceDefinition) node; - List> outputs = new ArrayList<>(choice.getWhenClauses()); - if (choice.getOtherwise() != null) { - outputs.add(choice.getOtherwise()); - } - this.outputs = outputs; - } else if (node instanceof RecipientListDefinition) { - this.image = imagePrefix + "RecipientListIcon.png"; - this.nodeType = "Recipient List"; - } else if (node instanceof RoutingSlipDefinition) { - this.image = imagePrefix + "RoutingTableIcon.png"; - this.nodeType = "Routing Slip"; - this.url = "http://camel.apache.org/routing-slip.html"; - } else if (node instanceof SplitDefinition) { - this.image = imagePrefix + "SplitterIcon.png"; - this.nodeType = "Splitter"; - } else if (node instanceof AggregateDefinition) { - this.image = imagePrefix + "AggregatorIcon.png"; - this.nodeType = "Aggregator"; - } else if (node instanceof ResequenceDefinition) { - this.image = imagePrefix + "ResequencerIcon.png"; - this.nodeType = "Resequencer"; - } else if (node instanceof BeanDefinition) { - BeanDefinition beanRef = (BeanDefinition) node; - this.nodeType = "Bean Ref"; - this.label = beanRef.getLabel() + " Bean"; - this.shape = "box"; - } else if (node instanceof TransformDefinition) { - this.nodeType = "Transform"; - this.url = "http://camel.apache.org/message-translator.html"; - } - - // lets auto-default as many values as we can - if (isEmpty(this.nodeType) && node != null) { - String name = node.getClass().getName(); - int idx = name.lastIndexOf('.'); - if (idx > 0) { - name = name.substring(idx + 1); - } - if (name.endsWith("Type")) { - name = name.substring(0, name.length() - 4); - } - this.nodeType = insertSpacesBetweenCamelCase(name); - } - if (this.label == null) { - if (isEmpty(this.image)) { - this.label = this.nodeType; - this.shape = "box"; - } else if (isNotEmpty(this.edgeLabel)) { - this.label = ""; - } else { - this.label = String.valueOf(node); - } - } - if (isEmpty(this.tooltip)) { - if (isNotEmpty(this.nodeType)) { - String description = isNotEmpty(this.edgeLabel) ? this.edgeLabel : this.label; - this.tooltip = this.nodeType + ": " + description; - } else { - this.tooltip = this.label; - } - } - if (isEmpty(this.url) && isNotEmpty(this.nodeType)) { - this.url = - "http://camel.apache.org/" - + this.nodeType.toLowerCase(Locale.ENGLISH).replace(' ', '-') - + ".html"; - } - if (node instanceof ProcessorDefinition && this.outputs == null) { - ProcessorDefinition processorType = (ProcessorDefinition) node; - this.outputs = processorType.getOutputs(); - } - } - - protected String removeQueryString(String text) { - int idx = text.indexOf('?'); - if (idx <= 0) { - return text; - } else { - return text.substring(0, idx); - } - } - - /** Inserts a space before each upper case letter after a lowercase */ - public static String insertSpacesBetweenCamelCase(String name) { - boolean lastCharacterLowerCase = false; - StringBuilder buffer = new StringBuilder(); - int i = 0; - for (int size = name.length(); i < size; i++) { - char ch = name.charAt(i); - if (Character.isUpperCase(ch)) { - if (lastCharacterLowerCase) { - buffer.append(' '); - } - lastCharacterLowerCase = false; - } else { - lastCharacterLowerCase = true; - } - buffer.append(ch); - } - return buffer.toString(); - } -} diff --git a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/PrologNode.java b/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/PrologNode.java deleted file mode 100644 index 6f3cf38d2..000000000 --- a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/PrologNode.java +++ /dev/null @@ -1,126 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-route-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.rm.util; - -import static org.apache.camel.util.ObjectHelper.isEmpty; -import static org.apache.camel.util.ObjectHelper.isNotEmpty; - -import java.util.ArrayList; -import java.util.List; -import org.apache.camel.model.AggregateDefinition; -import org.apache.camel.model.BeanDefinition; -import org.apache.camel.model.ChoiceDefinition; -import org.apache.camel.model.FilterDefinition; -import org.apache.camel.model.FromDefinition; -import org.apache.camel.model.OtherwiseDefinition; -import org.apache.camel.model.ProcessorDefinition; -import org.apache.camel.model.RecipientListDefinition; -import org.apache.camel.model.ResequenceDefinition; -import org.apache.camel.model.RoutingSlipDefinition; -import org.apache.camel.model.SplitDefinition; -import org.apache.camel.model.ToDefinition; -import org.apache.camel.model.TransformDefinition; -import org.apache.camel.model.WhenDefinition; -import org.checkerframework.checker.nullness.qual.NonNull; - -/** Represents a node in the EIP diagram tree */ -public class PrologNode { - // public String id; - public String nodeType; - public String value; - // public String predicate = "has_url"; - public List> outputs; - - public PrologNode(@NonNull String id, @NonNull Object node) { - // this.id = id; - - if (node instanceof ProcessorDefinition) { - ProcessorDefinition processorType = (ProcessorDefinition) node; - // this.predicate = "has_operation"; - this.value = processorType.getLabel(); - } - if (node instanceof FromDefinition) { - FromDefinition fromType = (FromDefinition) node; - this.nodeType = "from"; - // this.predicate = "has_url"; - this.value = fromType.getEndpointUri(); - } else if (node instanceof ToDefinition) { - ToDefinition toType = (ToDefinition) node; - this.value = toType.getEndpointUri(); - this.nodeType = "to"; - } else if (node instanceof FilterDefinition) { - this.nodeType = "message_filter"; - } else if (node instanceof WhenDefinition) { - this.nodeType = "when"; - this.value = ((WhenDefinition) node).getExpression().getExpression(); - } else if (node instanceof OtherwiseDefinition) { - this.nodeType = "otherwise"; - this.value = ""; - } else if (node instanceof ChoiceDefinition) { - ChoiceDefinition choice = (ChoiceDefinition) node; - List> outputs = new ArrayList<>(choice.getWhenClauses()); - if (choice.getOtherwise() != null) { - outputs.add(choice.getOtherwise()); - } - this.outputs = outputs; - this.nodeType = "choice"; - } else if (node instanceof RecipientListDefinition) { - // this.predicate = "recipient_list"; - this.value = ((RecipientListDefinition) node).getLabel(); - this.nodeType = "recipients"; - } else if (node instanceof RoutingSlipDefinition) { - this.value = ((RoutingSlipDefinition) node).getLabel(); - this.nodeType = "slip"; - } else if (node instanceof SplitDefinition) { - this.nodeType = "splitter"; - } else if (node instanceof AggregateDefinition) { - this.nodeType = "aggregator"; - } else if (node instanceof ResequenceDefinition) { - // this.predicate = "resequence"; - this.value = ((ResequenceDefinition) node).getLabel(); - } else if (node instanceof BeanDefinition) { - // this.predicate = "bean"; - this.value = ((BeanDefinition) node).getLabel(); - } else if (node instanceof TransformDefinition) { - this.value = ((TransformDefinition) node).getLabel(); - // this.predicate = "transform"; - } - - // lets auto-default as many values as we can - if (isEmpty(this.nodeType) && node != null) { - String name = node.getClass().getName(); - int idx = name.lastIndexOf('.'); - if (idx > 0) { - name = name.substring(idx + 1); - } - if (name.endsWith("Type")) { - name = name.substring(0, name.length() - 4); - } - this.nodeType = name; - } - if (isEmpty(this.value) && isNotEmpty(this.nodeType)) { - this.value = this.nodeType; - } - if (node instanceof ProcessorDefinition && this.outputs == null) { - ProcessorDefinition processorType = (ProcessorDefinition) node; - this.outputs = processorType.getOutputs(); - } - } -} diff --git a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/PrologPrinter.java b/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/PrologPrinter.java deleted file mode 100644 index 915ca1d55..000000000 --- a/ids-route-manager/src/main/java/de/fhg/aisec/ids/rm/util/PrologPrinter.java +++ /dev/null @@ -1,125 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-route-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.rm.util; - -import org.apache.camel.model.ChoiceDefinition; -import org.apache.camel.model.OptionalIdentifiedDefinition; -import org.apache.camel.model.ProcessorDefinition; -import org.apache.camel.model.RouteDefinition; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.io.IOException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -public class PrologPrinter { - - /** - * Prints a single Camel route in Prolog representation. - * - * @param writer - * @param route - * @throws IOException - */ - public void printSingleRoute(@Nullable Writer writer, @Nullable RouteDefinition route) - throws IOException { - if (writer == null || route == null) { - return; - } - - // Print route entry points - printInput(writer, route); - } - - /** - * Prints a single node of a Camel route in Prolog representation. - * - * @param writer - * @param current - * @param preds - * @return - * @throws IOException - */ - private List> printNode( - Writer writer, ProcessorDefinition current, List> preds) - throws IOException { - for (OptionalIdentifiedDefinition p : preds) { - writer.write("succ(" + p.getId() + ", " + current.getId() + ").\n"); - } - writer.write("stmt(" + current.getId() + ").\n"); - writer.write("has_action(" + current.getId() + ", \"" + current.getLabel() + "\").\n"); - - // predecessor of next recursion is the current node - List> newPreds = new ArrayList<>(); - newPreds.add(current); - for (ProcessorDefinition out : current.getOutputs()) { - // if this is a ChoiceDefinition, there is no link between its WhereDefinitions. - ArrayList> myPreds = new ArrayList<>(); - if (current instanceof ChoiceDefinition) { - myPreds.add(current); - } else { - // @TODO: Looks somewhat strange... is this correct? - myPreds.addAll(newPreds); - } - - // Recursion ... - List> p = printNode(writer, out, myPreds); - - // Predecessors of a ChoiceDefinition are all last stmts of its Where- and - // OtherwiseDefinitions - if (current instanceof ChoiceDefinition) { - newPreds.addAll(p); - } else { - newPreds.clear(); - newPreds.addAll(p); - } - } - - return newPreds; - } - - /** - * Prints a single FromDefinition (= a route entry point) in Prolog representation. - * - * @throws IOException - */ - private void printInput(Writer writer, RouteDefinition route) - throws IOException { - AtomicInteger counter = new AtomicInteger(0); - var i = route.getInput(); - // Make sure every input node has a unique id - if (i.getId() == null) { - i.setCustomId(true); - i.setId("input" + counter.incrementAndGet()); - } - writer.write("stmt(" + i.getId() + ").\n"); - writer.write("entrynode(" + i.getId() + ").\n"); - writer.write("has_action(" + i.getId() + ", \"" + i.getLabel() + "\").\n"); - - OptionalIdentifiedDefinition prev = i; - for (ProcessorDefinition next : route.getOutputs()) { - printNode(writer, next, Collections.singletonList(prev)); - prev = next; - } - } -} diff --git a/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/CamelInterceptor.kt b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/CamelInterceptor.kt new file mode 100644 index 000000000..ec2488a88 --- /dev/null +++ b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/CamelInterceptor.kt @@ -0,0 +1,67 @@ +/*- + * ========================LICENSE_START================================= + * ids-route-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.rm + +import de.fhg.aisec.ids.api.cm.ContainerManager +import de.fhg.aisec.ids.api.idscp2.Idscp2UsageControlInterface +import de.fhg.aisec.ids.api.policy.PDP +import org.apache.camel.CamelContext +import org.apache.camel.NamedNode +import org.apache.camel.Processor +import org.apache.camel.spi.InterceptStrategy +import org.osgi.service.component.annotations.* + +@Component(immediate = true, name = "ids-camel-interceptor") +class CamelInterceptor : InterceptStrategy { + @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC) + @Volatile + private var pdp: PDP? = null + @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC) + @Volatile + private var usageControlInterface: Idscp2UsageControlInterface? = null + @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC) + @Volatile + private var containerManager: ContainerManager? = null + + @Activate + private fun activate() { + instance = this + } + + override fun wrapProcessorInInterceptors( + context: CamelContext, + node: NamedNode, + target: Processor, + nextTarget: Processor? + ): Processor { + return PolicyEnforcementPoint(node, target) + } + + companion object { + private lateinit var instance: CamelInterceptor + + val pdp + get() = instance.pdp + val usageControlInterface + get() = instance.usageControlInterface + val containerManager + get() = instance.containerManager + } +} diff --git a/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/PolicyEnforcementPoint.kt b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/PolicyEnforcementPoint.kt new file mode 100644 index 000000000..fe89f14da --- /dev/null +++ b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/PolicyEnforcementPoint.kt @@ -0,0 +1,287 @@ +/*- + * ========================LICENSE_START================================= + * ids-route-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.rm + +import com.google.common.collect.MapMaker +import de.fhg.aisec.ids.api.policy.DecisionRequest +import de.fhg.aisec.ids.api.policy.PolicyDecision +import de.fhg.aisec.ids.api.policy.ServiceNode +import de.fhg.aisec.ids.api.policy.TransformationDecision +import de.fraunhofer.iais.eis.BinaryOperator +import de.fraunhofer.iais.eis.Constraint +import de.fraunhofer.iais.eis.LeftOperand +import java.net.InetAddress +import java.net.URI +import java.util.* +import org.apache.camel.* +import org.apache.camel.model.EndpointRequiredDefinition +import org.apache.camel.model.FromDefinition +import org.apache.camel.model.RouteDefinition +import org.apache.camel.model.ToDefinition +import org.apache.camel.support.processor.DelegateAsyncProcessor +import org.slf4j.LoggerFactory + +class PolicyEnforcementPoint +internal constructor(private val destinationNode: NamedNode, target: Processor) : + DelegateAsyncProcessor(target) { + /** + * The method performs flow control and calls Exchange.setException() when necessary It iterates + * through nodes in CamelRoute (, , , , , ...) and launches node + * specific usage enforcement actions. + * + * At node : protect exchange msg's body if usage constraint is given At node : + * unprotect exchange msg's body if usage constraing it fulfilled + * + * @param exchange The exchange object to check + * @return Whether target.process() is to be called for this exchange object + */ + private fun processFlowControl(exchange: Exchange?): Boolean { + if (exchange == null) { + if (LOG.isWarnEnabled) { + LOG.warn("Cannot check data flow policy. Exchange object is null.") + } + return false + } + // Strict policy: If PDP or Usage Control interface are not available, block every checked + // data flow + val pdp = CamelInterceptor.pdp ?: throw Exception("PDP is not available") + val ucInterface = + CamelInterceptor.usageControlInterface + ?: throw Exception("Usage Control Interface is not available") + + // Save per exchange object the source node's content ( {}", source, destination) + } + + val isIdscp2Endpoint = { ep: EndpointRequiredDefinition -> + ep.endpointUri.startsWith("idscp2") + } + // Only take action for nodes of type (= input) and (= output) + if ((sourceNode is EndpointRequiredDefinition && isIdscp2Endpoint(sourceNode)) || + destinationNode is ToDefinition + ) { + val ucContract = + try { + ucInterface.getExchangeContract(exchange) + } catch (x: RuntimeException) { + // Thrown if data provider references an unknown ContractAgreement via + // transferContract + throw Exception("Required contract is not available!", x) + } + // If there is no known ContractAgreement for this Exchange, nothing to do here. + ucContract?.let { contract -> + if (LOG.isDebugEnabled) { + LOG.debug("Applying Contract $contract") + } + val dockerConstraint = { c: Constraint -> + c.operator == BinaryOperator.SAME_AS && c.leftOperand == LeftOperand.SYSTEM + } + contract + .permission + .firstOrNull { p -> + // Check whether any constraint is given which fits the rules given above + p.constraint.firstOrNull(dockerConstraint) != null + // So far previous checks answered: "Can we principally work with given + // constraint?" + } + ?.constraint + ?.first(dockerConstraint) + ?.rightOperandReference + ?.let { dockerUri -> + if (LOG.isDebugEnabled) { + LOG.debug("UC: Restricting to Container URI $dockerUri") + } + // Extracting hash and port of containerUri given by CamelRoute + val hashPart = dockerUri.path.split("/").last() + if (!hashPart.startsWith("sha256-")) { + throw Exception( + "Invalid docker URI for UC, last path component must start with \"sha256-\"!" + ) + } + val hash = hashPart.substring(7) + val port = + try { + dockerUri.fragment.toInt().also { assert(it in 1..65535) } + } catch (nfe: NumberFormatException) { + throw Exception( + "Invalid docker URI for UC, fragment must represent a valid port number!" + ) + } catch (ae: AssertionError) { + throw Exception( + "Invalid docker URI for UC, ${dockerUri.fragment} is not a valid port number!" + ) + } + // Check whether we deal with an entry node ("from:...") or a response of a + // To node ("to...")... + if (sourceNode is FromDefinition || + (sourceNode is ToDefinition && + !ucInterface.isProtected(exchange) && + isIdscp2Endpoint(sourceNode)) + ) { + // If we found an entry node, then protect exchange's body + ucInterface.protectBody(exchange, ucContract.id) + if (LOG.isDebugEnabled) { + LOG.debug( + "UC: Protect Exchange body with UC contract ${ucContract.id}" + ) + } + // ... or output ("to:...") node as destination of this transition. + // Additionally check whether exchange's body was protected. + } else if (destinationNode is ToDefinition && + ucInterface.isProtected(exchange) + ) { + // Compare hash value and port of camelRoute's containerUri with local + // Docker containers + CamelInterceptor.containerManager?.let { cm -> + val endpointUri = URI.create(destinationNode.endpointUri) + // Check is containerUri's port matched CamelRoute ToNode's port + if (port != endpointUri.port) { + LOG.warn( + "UC: Exchange blocked by contract: " + + "Port $port is permitted, but ${endpointUri.port} is used!" + ) + } else { + val allowedContainers = + cm.list(true).filter { container -> + // From running docker containers get all with the given + // hash + // Normally there is only one hash type, but there can + // be more + // Currently requested type is only sha256 (e.g. sha3 or + // else may be added later) + container.imageDigests.any { + it.split(":").last() == hash + } || container.imageId.split(":").last() == hash + } + // Save all ip addresses of allowed containers in one list + val allowedIPs = + allowedContainers.flatMap { it.ipAddresses }.toSet() + // Check whether all endpoint's ip-addresses belong to allowed + // containers + if (InetAddress.getAllByName(endpointUri.host).all { + allowedIPs.contains(it) + } + ) { + ucInterface.unprotectBody(exchange) + if (LOG.isDebugEnabled) { + LOG.debug( + "UC: Contract permits data flow, Exchange body has been restored." + ) + } + } else { + LOG.warn( + "UC: Some or all IP addresses of the host ${endpointUri.host} " + + "do not belong to the permitted containers (${allowedContainers})" + ) + } + } + } + ?: LOG.warn( + "UC: ContainerManager is not available, " + + "cannot verify container-binding contract!" + ) + } + } + } + } + + val sourceServiceNode = ServiceNode(source, null, null) + val destinationServiceNode = ServiceNode(destination, null, null) + + // Call PDP to transform labels and decide whether to forward the Exchange + applyLabelTransformation(pdp.requestTranformations(sourceServiceNode), exchange) + val labels = exchangeLabels.computeIfAbsent(exchange) { HashSet() } + val decision = + pdp.requestDecision( + DecisionRequest(sourceServiceNode, destinationServiceNode, labels, null) + ) + return when (decision.decision!!) { + PolicyDecision.Decision.ALLOW -> true + PolicyDecision.Decision.DENY -> { + if (LOG.isWarnEnabled) { + LOG.warn( + "Exchange explicitly blocked (DENY) by data flow policy. " + + "Source: {}, Target: {}", + sourceServiceNode, + destinationServiceNode + ) + } + exchange.setException(Exception("Exchange blocked by data flow policy")) + false + } + } + } + + /** + * Removes and adds labels to an exchange object. + * + * @param requestTransformations The request transformations (label changes) to be performed + * @param exchange Exchange processed + */ + private fun applyLabelTransformation( + requestTransformations: TransformationDecision, + exchange: Exchange + ) { + val labels = exchangeLabels.computeIfAbsent(exchange) { HashSet() } + + // Remove labels from exchange + labels.removeAll(requestTransformations.labelsToRemove) + + // Add labels to exchange + labels.addAll(requestTransformations.labelsToAdd) + } + + @Throws(Exception::class) + override fun process(exchange: Exchange, asyncCallback: AsyncCallback): Boolean { + if (processFlowControl(exchange)) { + return super.process(exchange, asyncCallback) + } else { + throw Exception("Exchange blocked by data flow policy") + } + } + + companion object { + private val LOG = LoggerFactory.getLogger(PolicyEnforcementPoint::class.java) + private val lastDestinations: MutableMap = + MapMaker().weakKeys().makeMap() + private val exchangeLabels: MutableMap> = + MapMaker().weakKeys().makeMap() + } +} diff --git a/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/RouteManagerService.kt b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/RouteManagerService.kt new file mode 100644 index 000000000..6f78f2ff5 --- /dev/null +++ b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/RouteManagerService.kt @@ -0,0 +1,508 @@ +/*- + * ========================LICENSE_START================================= + * ids-route-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.rm + +import de.fhg.aisec.ids.api.router.* +import de.fhg.aisec.ids.rm.util.CamelRouteToDot +import de.fhg.aisec.ids.rm.util.PrologPrinter +import java.io.* +import java.nio.charset.StandardCharsets +import java.util.* +import java.util.stream.Collectors +import javax.management.* +import javax.xml.bind.JAXBContext +import javax.xml.bind.JAXBException +import org.apache.camel.CamelContext +import org.apache.camel.Endpoint +import org.apache.camel.ServiceStatus +import org.apache.camel.impl.DefaultCamelContext +import org.apache.camel.management.DefaultManagementAgent +import org.apache.camel.model.ModelCamelContext +import org.apache.camel.model.ModelHelper +import org.apache.camel.model.RouteDefinition +import org.apache.camel.support.dump.RouteStatDump +import org.osgi.framework.FrameworkUtil +import org.osgi.framework.InvalidSyntaxException +import org.osgi.service.component.ComponentContext +import org.osgi.service.component.annotations.Activate +import org.osgi.service.component.annotations.Component +import org.slf4j.LoggerFactory + +/** + * Manages Camel routes. + * + * @author Julian Schuette (julian.schuette@aisec.fraunhofer.de) + */ +@Component(immediate = true, name = "ids-routemanager") +class RouteManagerService : RouteManager { + private lateinit var ctx: ComponentContext + + @Activate + private fun activate(ctx: ComponentContext) { + this.ctx = ctx + } + + override fun getRoutes(): List { + val result: MutableList = ArrayList() + val camelContexts = camelContexts + + // Create response + for (cCtx in camelContexts) { + val mcc = cCtx.adapt(ModelCamelContext::class.java) + for (rd in mcc.routeDefinitions) { + result.add(routeDefinitionToObject(cCtx, rd)) + } + } + return result + } + + override fun getRoute(id: String): RouteObject? { + val camelContexts = camelContexts + + // Create response + for (cCtx in camelContexts) { + val mcc = cCtx.adapt(ModelCamelContext::class.java) + val rd = mcc.getRouteDefinition(id) + if (rd != null) { + return routeDefinitionToObject(cCtx, rd) + } + } + return null + } + + @Throws(RouteException::class) + override fun startRoute(routeId: String) { + val camelC = camelContexts + for (cCtx in camelC) { + val rt = cCtx.getRoute(routeId) + if (rt != null) { + try { + cCtx.routeController.startRoute(routeId) + } catch (e: Exception) { + throw RouteException(e) + } + } + } + } + + @Throws(RouteException::class) + override fun stopRoute(routeId: String) { + val camelC = camelContexts + for (cCtx in camelC) { + val rt = cCtx.getRoute(routeId) + if (rt != null) { + try { + cCtx.routeController.stopRoute(routeId) + } catch (e: Exception) { + throw RouteException(e) + } + } + } + } + + override fun listComponents(): List { + val componentNames: MutableList = ArrayList() + val bCtx = + FrameworkUtil.getBundle(RouteManagerService::class.java).bundleContext + ?: return componentNames + try { + val services = bCtx.getServiceReferences("org.apache.camel.spi.ComponentResolver", null) + for (sr in services) { + var bundle = sr.bundle.headers["Bundle-Name"] + if (bundle == null || "" == bundle) { + bundle = sr.bundle.symbolicName + } + var description = sr.bundle.headers["Bundle-Description"] + if (description == null) { + description = "" + } + componentNames.add(RouteComponent(bundle, description)) + } + } catch (e: InvalidSyntaxException) { + LOG.error(e.message, e) + } + return componentNames + } + + override fun getEndpoints(): Map> { + return camelContexts + .stream() + .collect( + Collectors.toMap( + { obj: CamelContext -> obj.name }, + { c: CamelContext -> + c.endpoints + .stream() + .map { obj: Endpoint -> obj.endpointUri } + .collect(Collectors.toList()) + } + ) + ) + } + + override fun listEndpoints(): Map { + val epURIs: MutableMap = HashMap() + for (cCtx in camelContexts) { + for ((key, value) in cCtx.endpointRegistry) { + epURIs[key!!.get()] = value.endpointUri + } + } + return epURIs + } + + override fun getRouteMetrics(): Map { + val rdump: MutableMap = HashMap() + val cCtxs = camelContexts + for (cCtx in cCtxs) { + val mcc = cCtx.adapt(ModelCamelContext::class.java) + val rds = mcc.routeDefinitions + for (rd in rds) { + var stat: RouteStatDump? + try { + stat = getRouteStats(cCtx, rd) + if (stat != null) { + val m = RouteMetrics() + m.completed = stat.exchangesCompleted + m.redeliveries = stat.redeliveries + m.failed = stat.exchangesFailed + m.failuresHandled = stat.failuresHandled + m.inflight = stat.exchangesInflight + m.maxProcessingTime = stat.maxProcessingTime + m.minProcessingTime = stat.minProcessingTime + m.meanProcessingTime = stat.meanProcessingTime + rdump[rd.id] = m + } + } catch (e: MalformedObjectNameException) { + LOG.error(e.message, e) + } catch (e: AttributeNotFoundException) { + LOG.error(e.message, e) + } catch (e: InstanceNotFoundException) { + LOG.error(e.message, e) + } catch (e: MBeanException) { + LOG.error(e.message, e) + } catch (e: ReflectionException) { + LOG.error(e.message, e) + } catch (e: JAXBException) { + LOG.error(e.message, e) + } + } + } + return rdump + } + + override fun delRoute(routeId: String) { + val cCtxs = camelContexts + for (cCtx in cCtxs) { + val mcc = cCtx.adapt(ModelCamelContext::class.java) + for (rd in mcc.routeDefinitions) { + if (rd.id == routeId) { + try { + cCtx.removeRoute(rd.id) + } catch (e: Exception) { + LOG.error(e.message, e) + } + return + } + } + } + } + + // sort the list + private val camelContexts: List + get() { + return try { + ctx.bundleContext.getServiceReferences(CamelContext::class.java.name, null)?.run { + mapNotNull { reference -> ctx.bundleContext.getService(reference) } + .map { CamelContext::class.java.cast(it) } + .sortedWith(Comparator.comparing { it.name }) + } + ?: emptyList() + } catch (e: Exception) { + LOG.warn("Cannot retrieve the list of Camel contexts.", e) + emptyList() + } + } + + /** + * Wraps a RouteDefinition in a RouteObject for use over API. + * + * @param cCtx Camel Context + * @param rd The RouteDefinition to be transformed + * @return The resulting RouteObject + */ + private fun routeDefinitionToObject(cCtx: CamelContext, rd: RouteDefinition): RouteObject { + return RouteObject( + rd.id, + rd.descriptionText, + routeToDot(rd), + rd.shortName, + cCtx.name, + cCtx.uptimeMillis, + cCtx.routeController.getRouteStatus(rd.id).toString() + ) + } + + /** + * Creates a visualization of a Camel route in DOT (graphviz) format. + * + * @param rd The route definition to process + * @return The string representation of the Camel route in DOT + */ + private fun routeToDot(rd: RouteDefinition): String { + var result = "" + try { + val viz = CamelRouteToDot() + val bos = ByteArrayOutputStream() + val writer = BufferedWriter(OutputStreamWriter(bos, StandardCharsets.UTF_8)) + viz.printSingleRoute(writer, rd) + writer.flush() + result = bos.toString(StandardCharsets.UTF_8) + } catch (e: IOException) { + LOG.error(e.message, e) + } + return result + } + + override fun getRouteInputUris(routeId: String): List { + for (ctx in camelContexts) { + val mcc = ctx.adapt(ModelCamelContext::class.java) + for (rd in mcc.routeDefinitions) { + if (routeId == rd.id) { + return listOf(rd.input.uri) + } + } + } + return emptyList() + } + + @Throws( + MalformedObjectNameException::class, + JAXBException::class, + AttributeNotFoundException::class, + InstanceNotFoundException::class, + MBeanException::class, + ReflectionException::class + ) + fun getRouteStats(cCtx: CamelContext, rd: RouteDefinition): RouteStatDump? { + val context = JAXBContext.newInstance(RouteStatDump::class.java) + val unmarshaller = context.createUnmarshaller() + val agent = cCtx.managementStrategy.managementAgent + if (agent != null) { + val mBeanServer = agent.mBeanServer + val set = + mBeanServer.queryNames( + ObjectName( + DefaultManagementAgent.DEFAULT_DOMAIN + + ":type=routes,name=\"" + + rd.id + + "\",*" + ), + null + ) + for (routeMBean in set) { + // the route must be part of the camel context + val camelId = mBeanServer.getAttribute(routeMBean, "CamelId") as String? + if (camelId != null && camelId == cCtx.name) { + val xml = + mBeanServer.invoke( + routeMBean, + "dumpRouteStatsAsXml", + arrayOf(false, true), + arrayOf("boolean", "boolean") + ) as + String + return unmarshaller.unmarshal(StringReader(xml)) as RouteStatDump + } + } + } + return null + } + + /** + * Retrieves the Prolog representation of a route + * + * @param routeId The id of the route that is to be exported + */ + override fun getRouteAsProlog(routeId: String): String { + val c = + camelContexts + .parallelStream() + .filter { cCtx: CamelContext -> + cCtx.adapt(ModelCamelContext::class.java).getRouteDefinition(routeId) != null + } + .findAny() + if (c.isPresent) { + try { + val rd = c.get().adapt(ModelCamelContext::class.java).getRouteDefinition(routeId) + val writer = StringWriter() + PrologPrinter().printSingleRoute(writer, rd) + writer.flush() + return writer.toString() + } catch (e: IOException) { + LOG.error("Error printing route to prolog $routeId", e) + } + } + return "" + } + + /** + * Retrieves the textual representation of a route + * + * @param routeId The id of the route that is to be exported + */ + override fun getRouteAsString(routeId: String): String? { + for (c in camelContexts) { + val rd = c.adapt(ModelCamelContext::class.java).getRouteDefinition(routeId) ?: continue + try { + return ModelHelper.dumpModelAsXml(c, rd) + } catch (e: JAXBException) { + LOG.error(e.message, e) + } + } + return null + } + + /** + * Save a route, replacing it with a new representation within the same context + * + * @param routeId ID of the route to save + * @param routeRepresentation The new textual representation of the route (XML etc.) + * @throws RouteException If the route does not exist or some Exception was thrown during route + * replacement. + */ + @Throws(RouteException::class) + override fun saveRoute(routeId: String, routeRepresentation: String): RouteObject { + LOG.debug("Save route \"$routeId\": $routeRepresentation") + var cCtx: CamelContext? = null + var routeStarted = false + + // Find the state and CamelContext of the route to be saved + for (c in camelContexts) { + val targetRoute = c.getRoute(routeId) + if (targetRoute != null) { + cCtx = c + val serviceStatus = cCtx.routeController.getRouteStatus(routeId) + routeStarted = + serviceStatus == ServiceStatus.Started || + serviceStatus == ServiceStatus.Starting + break + } + } + if (cCtx == null) { + LOG.error("Could not find route with id \"$routeId\"") + throw RouteException("Could not find route with id \"$routeId\"") + } + + // Check for validity of route representation + var routes: List + try { + ByteArrayInputStream(routeRepresentation.toByteArray(StandardCharsets.UTF_8)).use { bis + -> + // Load route(s) from XML + val rd = ModelHelper.loadRoutesDefinition(cCtx, bis) + routes = rd.routes + val id = + routes + .stream() + .map { obj: RouteDefinition -> obj.id } + .filter { rid: String -> routeId != rid } + .findAny() + if (id.isPresent) { + throw Exception( + "The new route representation has a different ID: " + + "Expected \"" + + routeId + + "\" but got \"" + + id.get() + + "\"" + ) + } + } + } catch (e: Exception) { + LOG.error(e.message, e) + throw RouteException(e) + } + + // Remove old route from CamelContext + try { + cCtx.removeRoute(routeId) + } catch (e: Exception) { + LOG.error("Error while removing old route \"$routeId\"", e) + throw RouteException(e) + } + + // Add new route and start it if it was started/starting before save + return try { + val routeDefinition = routes[0] + cCtx.adapt(ModelCamelContext::class.java).addRouteDefinition(routeDefinition) + if (routeStarted) { + cCtx.routeController.startRoute(routeDefinition.id) + } + routeDefinitionToObject(cCtx, routeDefinition) + } catch (e: Exception) { + LOG.error("Error while adding new route \"$routeId\"", e) + throw RouteException(e) + } + } + + /** + * Create a new route in a fresh context from text + * + * @param routeRepresentation The textual representation of the route to be inserted + * @throws RouteException If a route with that name already exists + */ + @Throws(RouteException::class) + override fun addRoute(routeRepresentation: String) { + LOG.debug("Adding new route: $routeRepresentation") + val existingRoutes = this.routes + val cCtx: CamelContext = DefaultCamelContext() + try { + ByteArrayInputStream(routeRepresentation.toByteArray(StandardCharsets.UTF_8)).use { bis + -> + // Load route(s) from XML + val rd = ModelHelper.loadRoutesDefinition(cCtx, bis) + val routes = rd.routes + // Check that intersection of existing and new routes is empty (=we do not allow + // overwriting + // existing route ids) + val intersect = + routes + .stream() + .filter { r -> existingRoutes.stream().anyMatch { it.id == r.id } } + .map { it.id } + .collect(Collectors.toList()) + if (intersect.isNotEmpty()) { + throw RouteException( + "Route id already exists. Will not overwrite it. ${intersect.joinToString(", ")}" + ) + } + cCtx.adapt(ModelCamelContext::class.java).addRouteDefinitions(routes) + cCtx.start() + } + } catch (e: Exception) { + LOG.error(e.message, e) + throw RouteException(e) + } + } + + companion object { + private val LOG = LoggerFactory.getLogger(RouteManagerService::class.java) + } +} diff --git a/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/CamelRouteToDot.kt b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/CamelRouteToDot.kt new file mode 100644 index 000000000..d70a642e8 --- /dev/null +++ b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/CamelRouteToDot.kt @@ -0,0 +1,237 @@ +/*- + * ========================LICENSE_START================================= + * ids-route-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.rm.util + +import java.io.IOException +import java.io.PrintWriter +import java.io.Writer +import java.util.* +import org.apache.camel.model.* +import org.apache.camel.util.ObjectHelper + +/** + * Camel route definition to GraphViz converter. + * + * The output can be turned into pictures using dot, neato, and others. + */ +class CamelRouteToDot { + private val nodeMap: MutableMap = IdentityHashMap() + private var clusterCounter = 0 + + @Throws(IOException::class) + private fun printRoutes(writer: Writer, map: Map>) { + val entries = map.entries + for ((group, value) in entries) { + printRoutes(writer, group, value) + } + } + + @Throws(IOException::class) + private fun printRoutes(writer: Writer, group: String?, routes: List) { + if (group != null) { + writer.write("""subgraph cluster_${clusterCounter++} { +""") + writer.write("label = \"$group\";\n") + writer.write("color = grey;\n") + writer.write("style = \"dashed\";\n") + } + for (route in routes) { + printRoute(writer, route, route.input) + writer.write("\n") + } + if (group != null) { + writer.write("}\n\n") + } + } + + /** + * Prints graphviz code of a single RouteDefinition to the provided PrintWriter. + * + * @param writer + * @param route + * @throws IOException + */ + @Throws(IOException::class) + fun printSingleRoute(writer: Writer?, route: RouteDefinition?) { + if (writer == null || route == null) { + return + } + writer.write("digraph { rankdir=LR; size=\"4.5,5.5\" \n\n") + writer.write( + "node [shape=\"box\", style = \"filled\", fillcolor = white, " + + "fontname=\"Helvetica-Oblique\"];" + ) + printRoute(writer, route, route.input) + writer.write("\n}") + } + + @Throws(IOException::class) + private fun printRoute(writer: Writer, route: RouteDefinition, input: FromDefinition) { + val nodeData = getNodeData(input) + printNode(writer, nodeData) + var from: NodeData? = nodeData + for (output in route.outputs) { + from = printNode(writer, from, output) + } + } + + @Throws(IOException::class) + private fun printNode( + writer: Writer, + fromData: NodeData?, + node: ProcessorDefinition<*>? + ): NodeData? { + var fromDataVar = fromData + if (node is MulticastDefinition) { + // no need for a multicast or interceptor node + val outputs = node.getOutputs() + val isPipeline = isPipeline(node) + for (output in outputs) { + val out = printNode(writer, fromDataVar, output) + // if in pipeline then we should move the from node to the next + // in the pipeline + if (isPipeline) { + fromDataVar = out + } + } + return fromDataVar + } + var toData: NodeData? = getNodeData(node!!) + printNode(writer, toData) + if (fromDataVar != null) { + writer.write(fromDataVar.id) + writer.write(" -> ") + writer.write(toData!!.id) + writer.write(" [\n") + val label = fromDataVar.edgeLabel + if (ObjectHelper.isNotEmpty(label)) { + writer.write("label = \"$label\"\n") + } + writer.write("];\n") + } + + // now lets write any children + val outputs = toData!!.outputs + if (outputs != null) { + for (output in outputs) { + val newData = printNode(writer, toData, output) + if (!isMulticastNode(node)) { + toData = newData + } + } + } + return toData + } + + @Throws(IOException::class) + private fun printNode(writer: Writer, data: NodeData?) { + if (!data!!.nodeWritten) { + data.nodeWritten = true + writer.write("\n") + writer.write(""" + ${data.id} + + """.trimIndent()) + writer.write(" [\n") + writer.write(""" + label = "${data.label}" + + """.trimIndent()) + writer.write(""" + tooltip = "${data.tooltip}" + + """.trimIndent()) + val image = data.image + if (image != null) { + writer.write("shapefile = \"$image\"\n") + writer.write("peripheries=0") + } + var shape = data.shape + if (shape == null && image != null) { + shape = "custom" + } + if (shape != null) { + writer.write("shape = \"$shape\"\n") + } + writer.write("];\n\n") + } + } + + @Throws(IOException::class) + fun generateFile(writer: PrintWriter?, map: Map>?) { + if (writer == null || map == null) { + return + } + writer.println("digraph CamelRoutes {") + writer.println() + writer.println( + "node [style = \"rounded,filled\", fillcolor = white, color = \"#898989\", " + + "fontname=\"Helvetica-Oblique\"];" + ) + writer.println() + printRoutes(writer, map) + writer.println("}") + } + + private fun getNodeData(node: Any): NodeData { + var key = node + if (node is FromDefinition) { + key = node.uri + } else if (node is ToDefinition) { + key = node.uri + } + var answer: NodeData? = nodeMap[key] + if (answer == null) { + val id = "node" + (nodeMap.size + 1) + answer = NodeData(id, node, PREFIX) + nodeMap[key] = answer + } + return answer + } + + private fun isMulticastNode(node: ProcessorDefinition<*>?): Boolean { + return node is MulticastDefinition || node is ChoiceDefinition + } + + /** Is the given node a pipeline */ + private fun isPipeline(node: ProcessorDefinition<*>): Boolean { + if (node is MulticastDefinition) { + return false + } + if (node is PipelineDefinition) { + return true + } + if (node.outputs.size > 1) { + // is pipeline if there is more than 1 output and they are all To + // types + for (type in node.outputs) { + if (type !is ToDefinition) { + return false + } + } + return true + } + return false + } + + companion object { + private const val PREFIX = "http://www.eaipatterns.com/img/" + } +} diff --git a/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/GraphProcessor.kt b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/GraphProcessor.kt new file mode 100644 index 000000000..a46df4e8d --- /dev/null +++ b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/GraphProcessor.kt @@ -0,0 +1,113 @@ +/*- + * ========================LICENSE_START================================= + * ids-route-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.rm.util + +import de.fhg.aisec.ids.api.router.graph.Edge +import de.fhg.aisec.ids.api.router.graph.GraphData +import de.fhg.aisec.ids.api.router.graph.Node +import java.util.* +import java.util.concurrent.atomic.AtomicInteger +import org.apache.camel.model.ChoiceDefinition +import org.apache.camel.model.OptionalIdentifiedDefinition +import org.apache.camel.model.ProcessorDefinition +import org.apache.camel.model.RouteDefinition + +object GraphProcessor { + /** + * Prints a single Camel route in Prolog representation. + * + * @param route The route to be transformed + */ + fun processRoute(route: RouteDefinition): GraphData { + val gd = GraphData() + // Print route entry points + processInput(gd, route) + return gd + } + + /** + * Prints a single node of a Camel route in Prolog representation. + * + * @param graphData + * @param current + * @param preds + * @return + */ + private fun processNode( + graphData: GraphData, + current: ProcessorDefinition<*>, + preds: List> + ): List> { + for (p in preds) { + graphData.addEdge(Edge(p.id, current.id)) + } + graphData.addNode( + Node( + current.id, + current.label, + if (current is ChoiceDefinition) Node.NodeType.ChoiceNode else Node.NodeType.Node + ) + ) + + // predecessor of next recursion is the current node + val newPreds: MutableList> = ArrayList() + newPreds.add(current) + for (out in current.outputs) { + // if this is a ChoiceDefinition, there is no link between its WhereDefinitions. + val myPreds = ArrayList>() + if (current is ChoiceDefinition) { + myPreds.add(current) + } else { + // @TODO: Looks somewhat strange... is this correct? + myPreds.addAll(newPreds) + } + + // Recursion ... + val p = processNode(graphData, out, myPreds) + + // Predecessors of a ChoiceDefinition are all last stmts of its Where- and + // OtherwiseDefinitions + if (current is ChoiceDefinition) { + newPreds.addAll(p) + } else { + newPreds.clear() + newPreds.addAll(p) + } + } + return newPreds + } + + /** Prints a single FromDefinition (= a route entry point) in Prolog representation. */ + private fun processInput(graphData: GraphData, route: RouteDefinition) { + val counter = AtomicInteger(0) + val i = route.input + // Make sure every input node has a unique id + if (i.id == null) { + i.customId = true + i.id = "input$counter" + } + graphData.addNode(Node(i.id, i.label, Node.NodeType.EntryNode)) + var prev: OptionalIdentifiedDefinition<*>? = i + for (next in route.outputs) { + processNode(graphData, next, prev?.let { listOf(it) } ?: emptyList()) + prev = next + } + } +} diff --git a/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/NodeData.kt b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/NodeData.kt new file mode 100644 index 000000000..508dcb2cb --- /dev/null +++ b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/NodeData.kt @@ -0,0 +1,189 @@ +/*- + * ========================LICENSE_START================================= + * ids-route-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.rm.util + +import java.util.* +import org.apache.camel.model.* +import org.apache.camel.util.ObjectHelper + +/** Represents a node in Graphviz representation of a route. */ +class NodeData(var id: String, node: Any?, imagePrefix: String) { + var image: String? = null + var label: String? = null + var shape: String? = null + var edgeLabel: String? = null + var tooltip: String? = null + var nodeType: String? = null + var nodeWritten = false + var url: String? = null + var outputs: List>? = null + + private fun removeQueryString(text: String?): String? { + val idx = text!!.indexOf('?') + return if (idx <= 0) { + text + } else { + text.substring(0, idx) + } + } + + companion object { + /** Inserts a space before each upper case letter after a lowercase */ + fun insertSpacesBetweenCamelCase(name: String): String { + var lastCharacterLowerCase = false + val buffer = StringBuilder() + var i = 0 + val size = name.length + while (i < size) { + val ch = name[i] + lastCharacterLowerCase = + if (Character.isUpperCase(ch)) { + if (lastCharacterLowerCase) { + buffer.append(' ') + } + false + } else { + true + } + buffer.append(ch) + i++ + } + return buffer.toString() + } + } + + init { + if (node is ProcessorDefinition<*>) { + edgeLabel = node.label + } + when (node) { + is FromDefinition -> { + tooltip = node.label + label = removeQueryString(tooltip) + url = "http://camel.apache.org/message-endpoint.html" + } + is ToDefinition -> { + tooltip = node.label + label = removeQueryString(tooltip) + edgeLabel = "" + url = "http://camel.apache.org/message-endpoint.html" + } + is FilterDefinition -> { + image = imagePrefix + "MessageFilterIcon.png" + label = "Filter" + nodeType = "Message Filter" + } + is WhenDefinition -> { + image = imagePrefix + "MessageFilterIcon.png" + nodeType = "When Filter" + label = "When" + url = "http://camel.apache.org/content-based-router.html" + } + is OtherwiseDefinition -> { + nodeType = "Otherwise" + edgeLabel = "" + url = "http://camel.apache.org/content-based-router.html" + tooltip = "Otherwise" + } + is ChoiceDefinition -> { + image = imagePrefix + "ContentBasedRouterIcon.png" + nodeType = "Content Based Router" + label = "Choice" + edgeLabel = "" + val choice = node + val outputs: MutableList> = ArrayList(choice.whenClauses) + if (choice.otherwise != null) { + outputs.add(choice.otherwise) + } + this.outputs = outputs + } + is RecipientListDefinition<*> -> { + image = imagePrefix + "RecipientListIcon.png" + nodeType = "Recipient List" + } + is RoutingSlipDefinition<*> -> { + image = imagePrefix + "RoutingTableIcon.png" + nodeType = "Routing Slip" + url = "http://camel.apache.org/routing-slip.html" + } + is SplitDefinition -> { + image = imagePrefix + "SplitterIcon.png" + nodeType = "Splitter" + } + is AggregateDefinition -> { + image = imagePrefix + "AggregatorIcon.png" + nodeType = "Aggregator" + } + is ResequenceDefinition -> { + image = imagePrefix + "ResequencerIcon.png" + nodeType = "Resequencer" + } + is BeanDefinition -> { + nodeType = "Bean Ref" + label = node.label + " Bean" + shape = "box" + } + is TransformDefinition -> { + nodeType = "Transform" + url = "http://camel.apache.org/message-translator.html" + } + } + + // lets auto-default as many values as we can + if (ObjectHelper.isEmpty(nodeType) && node != null) { + var name = node.javaClass.name + val idx = name.lastIndexOf('.') + if (idx > 0) { + name = name.substring(idx + 1) + } + if (name.endsWith("Type")) { + name = name.substring(0, name.length - 4) + } + nodeType = insertSpacesBetweenCamelCase(name) + } + if (label == null) { + if (ObjectHelper.isEmpty(image)) { + label = nodeType + shape = "box" + } else if (ObjectHelper.isNotEmpty(edgeLabel)) { + label = "" + } else { + label = node.toString() + } + } + if (ObjectHelper.isEmpty(tooltip)) { + if (ObjectHelper.isNotEmpty(nodeType)) { + val description = if (ObjectHelper.isNotEmpty(edgeLabel)) edgeLabel else label + tooltip = nodeType + ": " + description + } else { + tooltip = label + } + } + if (ObjectHelper.isEmpty(url) && ObjectHelper.isNotEmpty(nodeType)) { + url = + ("http://camel.apache.org/" + + nodeType!!.toLowerCase(Locale.ENGLISH).replace(' ', '-') + + ".html") + } + if (node is ProcessorDefinition<*> && outputs == null) { + outputs = node.outputs + } + } +} diff --git a/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/PrologNode.kt b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/PrologNode.kt new file mode 100644 index 000000000..efbd6c4e8 --- /dev/null +++ b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/PrologNode.kt @@ -0,0 +1,118 @@ +/*- + * ========================LICENSE_START================================= + * ids-route-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.rm.util + +import java.util.* +import org.apache.camel.model.* +import org.apache.camel.util.ObjectHelper + +/** Represents a node in the EIP diagram tree */ +class PrologNode(node: Any) { + // public String id; + private var nodeType: String? = null + private var value: String? = null + + // public String predicate = "has_url"; + private var outputs: List>? = null + + init { + // this.id = id; + if (node is ProcessorDefinition<*>) { + // this.predicate = "has_operation"; + value = node.label + } + when (node) { + is FromDefinition -> { + nodeType = "from" + // this.predicate = "has_url"; + value = node.endpointUri + } + is ToDefinition -> { + value = node.endpointUri + nodeType = "to" + } + is FilterDefinition -> { + nodeType = "message_filter" + } + is WhenDefinition -> { + nodeType = "when" + value = node.expression.expression + } + is OtherwiseDefinition -> { + nodeType = "otherwise" + value = "" + } + is ChoiceDefinition -> { + val outputs: MutableList> = ArrayList(node.whenClauses) + if (node.otherwise != null) { + outputs.add(node.otherwise) + } + this.outputs = outputs + nodeType = "choice" + } + is RecipientListDefinition<*> -> { + // this.predicate = "recipient_list"; + value = node.label + nodeType = "recipients" + } + is RoutingSlipDefinition<*> -> { + value = node.label + nodeType = "slip" + } + is SplitDefinition -> { + nodeType = "splitter" + } + is AggregateDefinition -> { + nodeType = "aggregator" + } + is ResequenceDefinition -> { + // this.predicate = "resequence"; + value = node.label + } + is BeanDefinition -> { + // this.predicate = "bean"; + value = node.label + } + is TransformDefinition -> { + value = node.label + // this.predicate = "transform"; + } + } + + // lets auto-default as many values as we can + if (ObjectHelper.isEmpty(nodeType)) { + var name = node.javaClass.name + val idx = name.lastIndexOf('.') + if (idx > 0) { + name = name.substring(idx + 1) + } + if (name.endsWith("Type")) { + name = name.substring(0, name.length - 4) + } + nodeType = name + } + if (ObjectHelper.isEmpty(value) && ObjectHelper.isNotEmpty(nodeType)) { + value = nodeType + } + if (node is ProcessorDefinition<*> && outputs == null) { + outputs = node.outputs + } + } +} diff --git a/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/PrologPrinter.kt b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/PrologPrinter.kt new file mode 100644 index 000000000..997128c65 --- /dev/null +++ b/ids-route-manager/src/main/kotlin/de/fhg/aisec/ids/rm/util/PrologPrinter.kt @@ -0,0 +1,141 @@ +/*- + * ========================LICENSE_START================================= + * ids-route-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.rm.util + +import java.io.IOException +import java.io.Writer +import java.util.* +import java.util.concurrent.atomic.AtomicInteger +import org.apache.camel.model.ChoiceDefinition +import org.apache.camel.model.OptionalIdentifiedDefinition +import org.apache.camel.model.ProcessorDefinition +import org.apache.camel.model.RouteDefinition + +class PrologPrinter { + /** + * Prints a single Camel route in Prolog representation. + * + * @param writer + * @param route + * @throws IOException + */ + @Throws(IOException::class) + fun printSingleRoute(writer: Writer?, route: RouteDefinition?) { + if (writer == null || route == null) { + return + } + + // Print route entry points + printInput(writer, route) + } + + /** + * Prints a single node of a Camel route in Prolog representation. + * + * @param writer + * @param current + * @param preds + * @return + * @throws IOException + */ + @Throws(IOException::class) + private fun printNode( + writer: Writer, + current: ProcessorDefinition<*>, + preds: List> + ): List> { + for (p in preds) { + writer.write(""" + succ(${p.id}, ${current.id}). + + """.trimIndent()) + } + writer.write(""" + stmt(${current.id}). + + """.trimIndent()) + writer.write( + """ + has_action(${current.id}, "${current.label}"). + + """.trimIndent() + ) + + // predecessor of next recursion is the current node + val newPreds: MutableList> = ArrayList() + newPreds.add(current) + for (out in current.outputs) { + // if this is a ChoiceDefinition, there is no link between its WhereDefinitions. + val myPreds = ArrayList>() + if (current is ChoiceDefinition) { + myPreds.add(current) + } else { + // @TODO: Looks somewhat strange... is this correct? + myPreds.addAll(newPreds) + } + + // Recursion ... + val p = printNode(writer, out, myPreds) + + // Predecessors of a ChoiceDefinition are all last stmts of its Where- and + // OtherwiseDefinitions + if (current is ChoiceDefinition) { + newPreds.addAll(p) + } else { + newPreds.clear() + newPreds.addAll(p) + } + } + return newPreds + } + + /** + * Prints a single FromDefinition (= a route entry point) in Prolog representation. + * + * @throws IOException + */ + @Throws(IOException::class) + private fun printInput(writer: Writer, route: RouteDefinition) { + val counter = AtomicInteger(0) + val i = route.input + // Make sure every input node has a unique id + if (i.id == null) { + i.customId = true + i.id = "input" + counter.incrementAndGet() + } + writer.write(""" + stmt(${i.id}). + + """.trimIndent()) + writer.write(""" + entrynode(${i.id}). + + """.trimIndent()) + writer.write(""" + has_action(${i.id}, "${i.label}"). + + """.trimIndent()) + var prev: OptionalIdentifiedDefinition<*>? = i + for (next in route.outputs) { + printNode(writer, next, prev?.let { listOf(it) } ?: emptyList()) + prev = next + } + } +} diff --git a/ids-comm/src/test/resources/log4j2-test.xml b/ids-route-manager/src/main/resources/log4j2-test.xml similarity index 100% rename from ids-comm/src/test/resources/log4j2-test.xml rename to ids-route-manager/src/main/resources/log4j2-test.xml diff --git a/ids-route-manager/src/test/java/de/fhg/aisec/ids/rm/RouteMetricsTest.java b/ids-route-manager/src/test/java/de/fhg/aisec/ids/rm/RouteMetricsTest.java deleted file mode 100644 index 205e3a773..000000000 --- a/ids-route-manager/src/test/java/de/fhg/aisec/ids/rm/RouteMetricsTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-route-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.rm; - -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.component.mock.MockEndpoint; -import org.apache.camel.model.ModelCamelContext; -import org.apache.camel.support.dump.RouteStatDump; -import org.apache.camel.test.junit4.CamelTestSupport; -import org.junit.Test; - -import java.util.Arrays; - -public class RouteMetricsTest extends CamelTestSupport { - protected static final String TEST_MESSAGE = "Hello World!"; - - @Test - public void testRouteStats() throws Exception { - final int MSG_COUNT = 123; - RouteManagerService rm = new RouteManagerService(); - MockEndpoint mock = getMockEndpoint("mock:result"); - var bodies = new String[MSG_COUNT]; - Arrays.fill(bodies, TEST_MESSAGE); - mock.expectedBodiesReceived(Arrays.asList(bodies)); - - // Send MSG_COUNT Exchange objects into this route - for (int i = 0; i < MSG_COUNT; i++) { - template.sendBody("direct:input", TEST_MESSAGE); - } - - // Make sure everything was received at the end of the route - mock.assertIsSatisfied(); - - // Retrieve route statistics from RouteManager and make sure they match expectations - RouteStatDump after = - rm.getRouteStats( - template.getCamelContext(), - template.getCamelContext().adapt(ModelCamelContext.class).getRouteDefinition("foo")); - assertEquals(MSG_COUNT, (long) after.getExchangesCompleted()); - assertEquals(0L, (long) after.getExchangesFailed()); - assertEquals(0L, (long) after.getRedeliveries()); - } - - @Override - protected RouteBuilder[] createRouteBuilders() { - // Define the most simple route for testing - RouteBuilder rb = new RouteBuilder() { - public void configure() { - from("direct:input") - .routeId("foo") - .log(">>> Message from direct to mock: ${body}") - .to("mock:result"); - } - }; - return new RouteBuilder[] { rb }; - } -} diff --git a/ids-route-manager/src/test/kotlin/de/fhg/aisec/ids/rm/RouteMetricsTest.kt b/ids-route-manager/src/test/kotlin/de/fhg/aisec/ids/rm/RouteMetricsTest.kt new file mode 100644 index 000000000..e894aa54f --- /dev/null +++ b/ids-route-manager/src/test/kotlin/de/fhg/aisec/ids/rm/RouteMetricsTest.kt @@ -0,0 +1,75 @@ +/*- + * ========================LICENSE_START================================= + * ids-route-manager + * %% + * Copyright (C) 2019 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ +package de.fhg.aisec.ids.rm + +import java.util.* +import org.apache.camel.builder.RouteBuilder +import org.apache.camel.model.ModelCamelContext +import org.apache.camel.test.junit4.CamelTestSupport +import org.junit.Test + +class RouteMetricsTest : CamelTestSupport() { + @Test + @Throws(Exception::class) + fun testRouteStats() { + val MSG_COUNT = 123 + val rm = RouteManagerService() + val mock = getMockEndpoint("mock:result") + val bodies = arrayOfNulls(MSG_COUNT) + Arrays.fill(bodies, TEST_MESSAGE) + mock.expectedBodiesReceived(listOf(*bodies)) + + // Send MSG_COUNT Exchange objects into this route + for (i in 0 until MSG_COUNT) { + template.sendBody("direct:input", TEST_MESSAGE) + } + + // Make sure everything was received at the end of the route + mock.assertIsSatisfied() + + // Retrieve route statistics from RouteManager and make sure they match expectations + val after = + rm.getRouteStats( + template.camelContext, + template.camelContext.adapt(ModelCamelContext::class.java).getRouteDefinition("foo") + ) + assertEquals(MSG_COUNT.toLong(), after!!.exchangesCompleted as Long) + assertEquals(0L, after.exchangesFailed as Long) + assertEquals(0L, after.redeliveries as Long) + } + + override fun createRouteBuilders(): Array { + // Define the most simple route for testing + val rb: RouteBuilder = + object : RouteBuilder() { + override fun configure() { + from("direct:input") + .routeId("foo") + .log(">>> Message from direct to mock: \${body}") + .to("mock:result") + } + } + return arrayOf(rb) + } + + companion object { + const val TEST_MESSAGE = "Hello World!" + } +} diff --git a/ids-settings/build.gradle.kts b/ids-settings/build.gradle.kts index 84df2acdf..608e13049 100644 --- a/ids-settings/build.gradle.kts +++ b/ids-settings/build.gradle.kts @@ -1,23 +1,16 @@ -import org.yaml.snakeyaml.Yaml +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map dependencies { - @Suppress("UNCHECKED_CAST") val libraryVersions = - Yaml().load(File("${rootDir}/libraryVersions.yaml").inputStream()) as Map - infomodelBundle(project(":ids-api")) { isTransitive = false } // Required by MapDB below - providedByBundle("com.google.guava", "guava", libraryVersions["guava"]) { - isTransitive = false // Avoid pulling in of checker framework and other annotation stuff - } + providedByBundle("com.google.guava", "guava", libraryVersions["guava"]) implementation ("org.mapdb", "mapdb", libraryVersions["mapdb"]) { // Exclude guava dependency, which is provided by bundle exclude("com.google.guava", "guava") exclude("org.jetbrains.kotlin", "*") } - providedByBundle("org.apache.logging.log4j", "log4j-core", libraryVersions["log4j"]) - providedByBundle("org.apache.logging.log4j", "log4j-slf4j-impl", libraryVersions["log4j"]) - osgiCore("org.osgi", "osgi.cmpn", libraryVersions["osgiCompendium"]) } \ No newline at end of file diff --git a/ids-settings/src/main/kotlin/de/fhg/aisec/ids/settings/OsgiElsaSerializer.kt b/ids-settings/src/main/kotlin/de/fhg/aisec/ids/settings/OsgiElsaSerializer.kt index 47917337c..02363907a 100644 --- a/ids-settings/src/main/kotlin/de/fhg/aisec/ids/settings/OsgiElsaSerializer.kt +++ b/ids-settings/src/main/kotlin/de/fhg/aisec/ids/settings/OsgiElsaSerializer.kt @@ -1,11 +1,28 @@ +/*- + * ========================LICENSE_START================================= + * ids-settings + * %% + * Copyright (C) 2021 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ package de.fhg.aisec.ids.settings import org.mapdb.DataInput2 import org.mapdb.DataOutput2 import org.mapdb.Serializer import org.mapdb.elsa.ElsaMaker -import org.mapdb.elsa.ElsaSerializer -import org.mapdb.elsa.ElsaSerializerBase import org.mapdb.elsa.ElsaSerializerPojo class OsgiElsaSerializer : Serializer { @@ -28,4 +45,4 @@ class OsgiElsaSerializer : Serializer { override fun deserialize(input: DataInput2, available: Int): T { return serializer.deserialize(input) } -} \ No newline at end of file +} diff --git a/ids-settings/src/main/kotlin/de/fhg/aisec/ids/settings/SettingsComponent.kt b/ids-settings/src/main/kotlin/de/fhg/aisec/ids/settings/SettingsComponent.kt index b2864d478..249779ce7 100644 --- a/ids-settings/src/main/kotlin/de/fhg/aisec/ids/settings/SettingsComponent.kt +++ b/ids-settings/src/main/kotlin/de/fhg/aisec/ids/settings/SettingsComponent.kt @@ -1,3 +1,22 @@ +/*- + * ========================LICENSE_START================================= + * ids-settings + * %% + * Copyright (C) 2021 Fraunhofer AISEC + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ package de.fhg.aisec.ids.settings import de.fhg.aisec.ids.api.Constants @@ -5,6 +24,10 @@ import de.fhg.aisec.ids.api.infomodel.ConnectorProfile import de.fhg.aisec.ids.api.settings.ConnectionSettings import de.fhg.aisec.ids.api.settings.ConnectorConfig import de.fhg.aisec.ids.api.settings.Settings +import java.nio.file.FileSystems +import java.util.* +import java.util.concurrent.ConcurrentMap +import kotlin.collections.HashMap import org.mapdb.DB import org.mapdb.DBMaker import org.mapdb.Serializer @@ -12,10 +35,6 @@ import org.osgi.service.component.annotations.Activate import org.osgi.service.component.annotations.Component import org.osgi.service.component.annotations.Deactivate import org.slf4j.LoggerFactory -import java.nio.file.FileSystems -import java.util.* -import java.util.concurrent.ConcurrentMap -import kotlin.collections.HashMap @Component(immediate = true, name = "ids-settings") class SettingsComponent : Settings { @@ -27,18 +46,23 @@ class SettingsComponent : Settings { var dbVersion = settingsStore.getOrPut(DB_VERSION_KEY, { 1 }) as Int // Check for unknown DB version if (dbVersion > CURRENT_DB_VERSION) { - LOG.error("Settings database is newer than supported version, data loss er errors are possible!") + LOG.error( + "Settings database is newer than supported version, data loss er errors are possible!" + ) } // Migrate old DB versions while (dbVersion < CURRENT_DB_VERSION) { - LOG.info("Migrating settings database from version $dbVersion to version $CURRENT_DB_VERSION...") + LOG.info( + "Migrating settings database from version $dbVersion to version $CURRENT_DB_VERSION..." + ) when (dbVersion) { 1 -> { // Checking ConnectorProfile for errors try { settingsStore[CONNECTOR_PROFILE_KEY] } catch (x: Exception) { - // Serialization issue due to infomodel changes, need to rebuild settings store + // Serialization issue due to infomodel changes, need to rebuild settings + // store val tempMap = HashMap() settingsStore.keys.forEach { if (it != CONNECTOR_PROFILE_KEY) { @@ -50,6 +74,10 @@ class SettingsComponent : Settings { } dbVersion = 2 } + 2 -> { + settingsStore -= DAT_KEY + dbVersion = 3 + } } settingsStore[DB_VERSION_KEY] = dbVersion mapDB.commit() @@ -64,7 +92,7 @@ class SettingsComponent : Settings { } override fun getConnectorConfig() = - settingsStore.getOrElse(CONNECTOR_SETTINGS_KEY) { ConnectorConfig() } as ConnectorConfig + settingsStore.getOrElse(CONNECTOR_SETTINGS_KEY) { ConnectorConfig() } as ConnectorConfig override fun setConnectorConfig(connectorConfig: ConnectorConfig) { settingsStore[CONNECTOR_SETTINGS_KEY] = connectorConfig @@ -72,7 +100,7 @@ class SettingsComponent : Settings { } override fun getConnectorProfile() = - settingsStore.getOrElse(CONNECTOR_PROFILE_KEY) { ConnectorProfile() } as ConnectorProfile + settingsStore.getOrElse(CONNECTOR_PROFILE_KEY) { ConnectorProfile() } as ConnectorProfile override fun setConnectorProfile(connectorProfile: ConnectorProfile) { settingsStore[CONNECTOR_PROFILE_KEY] = connectorProfile @@ -81,17 +109,6 @@ class SettingsComponent : Settings { override fun getConnectorJsonLd() = settingsStore[CONNECTOR_JSON_LD_KEY] as String? - override fun getDynamicAttributeToken() = settingsStore[DAT_KEY] as String? - - override fun setDynamicAttributeToken(dynamicAttributeToken: String?) { - if (dynamicAttributeToken == null) { - settingsStore -= DAT_KEY - } else { - settingsStore[DAT_KEY] = dynamicAttributeToken - } - mapDB.commit() - } - override fun setConnectorJsonLd(jsonLd: String?) { if (jsonLd == null) { settingsStore -= CONNECTOR_JSON_LD_KEY @@ -105,7 +122,9 @@ class SettingsComponent : Settings { if (connection == Constants.GENERAL_CONFIG) { connectionSettings.getOrElse(connection) { ConnectionSettings() } } else { - connectionSettings.getOrPut(connection) {getConnectionSettings(Constants.GENERAL_CONFIG)} + connectionSettings.getOrPut(connection) { + getConnectionSettings(Constants.GENERAL_CONFIG) + } } override fun setConnectionSettings(connection: String, conSettings: ConnectionSettings) { @@ -114,11 +133,11 @@ class SettingsComponent : Settings { } override fun getAllConnectionSettings(): MutableMap = - Collections.unmodifiableMap(connectionSettings) + Collections.unmodifiableMap(connectionSettings) companion object { internal const val DB_VERSION_KEY = "db_version" - internal const val CURRENT_DB_VERSION = 2 + internal const val CURRENT_DB_VERSION = 3 internal const val CONNECTOR_SETTINGS_KEY = "main_config" internal const val CONNECTOR_PROFILE_KEY = "connector_profile" internal const val CONNECTOR_JSON_LD_KEY = "connector_json_ld" @@ -127,16 +146,18 @@ class SettingsComponent : Settings { private val LOG = LoggerFactory.getLogger(SettingsComponent::class.java) private lateinit var mapDB: DB private val settingsStore: ConcurrentMap by lazy { - mapDB.hashMap("settings_store") - .keySerializer(Serializer.STRING) - .valueSerializer(OsgiElsaSerializer()) - .createOrOpen() + mapDB + .hashMap("settings_store") + .keySerializer(Serializer.STRING) + .valueSerializer(OsgiElsaSerializer()) + .createOrOpen() } private val connectionSettings: ConcurrentMap by lazy { - mapDB.hashMap("connection_settings") - .keySerializer(Serializer.STRING) - .valueSerializer(OsgiElsaSerializer()) - .createOrOpen() + mapDB + .hashMap("connection_settings") + .keySerializer(Serializer.STRING) + .valueSerializer(OsgiElsaSerializer()) + .createOrOpen() } } } diff --git a/ids-token-manager/LICENSE.txt b/ids-token-manager/LICENSE.txt deleted file mode 100755 index 261eeb9e9..000000000 --- a/ids-token-manager/LICENSE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/ids-token-manager/bnd.bnd b/ids-token-manager/bnd.bnd deleted file mode 100755 index eb54369e5..000000000 --- a/ids-token-manager/bnd.bnd +++ /dev/null @@ -1,6 +0,0 @@ -Bundle-Name: IDS :: Token Manager -Import-Package: \ - !com.android.org.conscrypt,\ - * -Private-Package: \ - io.jsonwebtoken*;-split-package:=merge-last \ No newline at end of file diff --git a/ids-token-manager/build.gradle b/ids-token-manager/build.gradle deleted file mode 100755 index cf2834569..000000000 --- a/ids-token-manager/build.gradle +++ /dev/null @@ -1,22 +0,0 @@ -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - osgiCore group: 'org.osgi', name: 'osgi.cmpn', version: libraryVersions.osgiCompendium - - providedByBundle group: 'io.jsonwebtoken', name: 'jjwt-impl', version: libraryVersions.jsonwebtoken - providedByBundle group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: libraryVersions.jsonwebtoken - providedByBundle group: 'io.jsonwebtoken', name: 'jjwt-api', version: libraryVersions.jsonwebtoken - providedByBundle group: 'com.squareup.okhttp3', name: 'okhttp', version: libraryVersions.okhttp - providedByBundle group: 'com.squareup.okio', name: 'okio', version: libraryVersions.okio - providedByBundle group: 'org.bitbucket.b_c', name: 'jose4j', version: libraryVersions.jose4j - providedByBundle group: 'org.json', name: 'json', version: libraryVersions.orgJson - - testImplementation group: 'junit', name: 'junit' - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito -} - - - diff --git a/ids-token-manager/src/main/java/de/fhg/aisec/ids/tokenmanager/TokenManagerService.java b/ids-token-manager/src/main/java/de/fhg/aisec/ids/tokenmanager/TokenManagerService.java deleted file mode 100755 index a8f374fe3..000000000 --- a/ids-token-manager/src/main/java/de/fhg/aisec/ids/tokenmanager/TokenManagerService.java +++ /dev/null @@ -1,355 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ids-token-manager - * %% - * Copyright (C) 2019 Fraunhofer AISEC - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package de.fhg.aisec.ids.tokenmanager; - -import de.fhg.aisec.ids.api.settings.ConnectionSettings; -import de.fhg.aisec.ids.api.settings.ConnectorConfig; -import de.fhg.aisec.ids.api.settings.Settings; -import de.fhg.aisec.ids.api.tokenm.DatException; -import de.fhg.aisec.ids.api.tokenm.TokenManager; -import io.jsonwebtoken.JwtBuilder; -import io.jsonwebtoken.JwtException; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import okhttp3.*; -import org.jose4j.http.Get; -import org.jose4j.jwk.HttpsJwks; -import org.jose4j.jws.AlgorithmIdentifiers; -import org.jose4j.jwt.JwtClaims; -import org.jose4j.jwt.MalformedClaimException; -import org.jose4j.jwt.consumer.ErrorCodes; -import org.jose4j.jwt.consumer.InvalidJwtException; -import org.jose4j.jwt.consumer.JwtConsumer; -import org.jose4j.jwt.consumer.JwtConsumerBuilder; -import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver; -import org.json.JSONObject; -import org.osgi.service.component.annotations.Activate; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Reference; -import org.osgi.service.component.annotations.ReferenceCardinality; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.*; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.*; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.time.Instant; -import java.util.Arrays; -import java.util.Date; -import java.util.Map; -import java.util.concurrent.TimeUnit; - - -/** - * Manages Dynamic Attribute Tokens. - * - * @author Gerd Brost (gerd.brost@aisec.fraunhofer.de) - */ -@Component(immediate = true, name = "ids-tokenmanager") -public class TokenManagerService implements TokenManager { - private static final Logger LOG = LoggerFactory.getLogger(TokenManagerService.class); - - @Reference(cardinality = ReferenceCardinality.MANDATORY) - private Settings settings = null; - private SSLSocketFactory sslSocketFactory = null; - - /** - * Method to aquire a Dynamic Attribute Token (DAT) from a Dynamic Attribute Provisioning Service - * (DAPS) - * - * @param targetDirectory The directory the keystore resides in - * @param dapsUrl The token aquiry URL (e.g., http://daps.aisec.fraunhofer.de/token - * @param keyStoreName Name of the keystore file (e.g., server-keystore.jks) - * @param keyStorePassword Password of keystore - * @param keystoreAliasName Alias of the connector's key entry. For default keystores with only - * one entry, this is '1' - * @param trustStoreName Name of the truststore file - * @param connectorUUID The UUID used to register the connector at the DAPS. Should be replaced by - * working code that does this automatically - */ - @Override - public Map acquireToken( - Path targetDirectory, - String dapsUrl, - String keyStoreName, - String keyStorePassword, - String keystoreAliasName, - String trustStoreName, - String connectorUUID) { - // This is a bug in the DAPS. - // Audience should not be set to default value "IDS_Connector" - String targetAudience = "IDS_Connector"; - String dynamicAttributeToken = "INVALID_TOKEN"; - Map jwtClaims = null; - - // Try clause for setup phase (loading keys, building trust manager) - try { - InputStream jksKeyStoreInputStream = - Files.newInputStream(targetDirectory.resolve(keyStoreName)); - InputStream jksTrustStoreInputStream = - Files.newInputStream(targetDirectory.resolve(trustStoreName)); - - KeyStore keystore = KeyStore.getInstance("JKS"); - KeyStore trustManagerKeyStore = KeyStore.getInstance("JKS"); - - LOG.info("Loading key store: " + keyStoreName); - LOG.info("Loading trus store: " + trustStoreName); - keystore.load(jksKeyStoreInputStream, keyStorePassword.toCharArray()); - trustManagerKeyStore.load(jksTrustStoreInputStream, keyStorePassword.toCharArray()); - java.security.cert.Certificate[] certs = trustManagerKeyStore.getCertificateChain("ca"); - LOG.info("Cert chain: " + Arrays.toString(certs)); - - LOG.info("LOADED CA CERT: " + trustManagerKeyStore.getCertificate("ca")); - jksKeyStoreInputStream.close(); - jksTrustStoreInputStream.close(); - - // get private key - Key privKey = keystore.getKey(keystoreAliasName, keyStorePassword.toCharArray()); - // Get certificate of public key - X509Certificate cert = (X509Certificate) keystore.getCertificate(keystoreAliasName); - - TrustManager[] trustManagers; - try { - TrustManagerFactory trustManagerFactory = - TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(trustManagerKeyStore); - trustManagers = trustManagerFactory.getTrustManagers(); - if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { - throw new IllegalStateException( - "Unexpected default trust managers:" + Arrays.toString(trustManagers)); - } - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, trustManagers, null); - sslSocketFactory = sslContext.getSocketFactory(); - } catch (GeneralSecurityException e) { - throw new RuntimeException(e); - } - - LOG.info("Retrieving Dynamic Attribute Token..."); - - // create signed JWT (JWS) - // Create expiry date one day (86400 seconds) from now - Date expiryDate = Date.from(Instant.now().plusSeconds(86400)); - JwtBuilder jwtb = - Jwts.builder() - .setIssuer(connectorUUID) - .setSubject(connectorUUID) - .setExpiration(expiryDate) - .setIssuedAt(Date.from(Instant.now())) - .setAudience(targetAudience) - .setNotBefore(Date.from(Instant.now())); - LOG.info("\tCertificate Subject: " + cert.getSubjectDN()); - String jws = jwtb.signWith(privKey, SignatureAlgorithm.RS256).compact(); - - // build form body to embed client assertion into post request - RequestBody formBody = - new FormBody.Builder() - .add("grant_type", "client_credentials") - .add( - "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") - .add("client_assertion", jws) - .add("scope", "ids_connector") - .build(); - - OkHttpClient.Builder builder = new OkHttpClient.Builder(); - - // configure client with trust manager - OkHttpClient client = - builder - .sslSocketFactory(this.sslSocketFactory, (X509TrustManager) trustManagers[0]) - .connectTimeout(15, TimeUnit.SECONDS) - .writeTimeout(15, TimeUnit.SECONDS) - .readTimeout(15, TimeUnit.SECONDS) - .build(); - - Request request = new Request.Builder().url(dapsUrl + "/token").post(formBody).build(); - Response jwtResponse = client.newCall(request).execute(); - if (!jwtResponse.isSuccessful()) { - throw new IOException("Unexpected code " + jwtResponse); - } - var responseBody = jwtResponse.body(); - if (responseBody == null) { - throw new Exception("JWT response is null."); - } - var jwtString = responseBody.string(); - LOG.info("Response body of token request:\n{}", jwtString); - - JSONObject jsonObject = new JSONObject(jwtString); - dynamicAttributeToken = jsonObject.getString("access_token"); - - LOG.info("Dynamic Attribute Token: " + dynamicAttributeToken); - - jwtClaims = verifyJWT(dynamicAttributeToken, targetAudience, dapsUrl); - } catch (KeyStoreException - | NoSuchAlgorithmException - | CertificateException - | UnrecoverableKeyException e) { - LOG.error("Cannot acquire token:", e); - } catch (IOException e) { - LOG.error("Error retrieving token:", e); - } catch (Exception e) { - LOG.error("Something else went wrong:", e); - } - - settings.setDynamicAttributeToken(dynamicAttributeToken); - - return jwtClaims; - } - - @Override - public Map verifyJWT( - String dynamicAttributeToken, - String targetAudience, - String dapsUrl) throws Exception { - if (sslSocketFactory == null) { - throw new JwtException("SSLSocketFactory is null, acquireToken() must be called first!"); - } - - try { - // The HttpsJwks retrieves and caches keys from a the given HTTPS JWKS endpoint. - // Because it retains the JWKs after fetching them, it can and should be reused - // to improve efficiency by reducing the number of outbound calls the the endpoint. - HttpsJwks httpsJkws = new HttpsJwks(dapsUrl + "/.well-known/jwks.json"); - Get getInstance = new Get(); - getInstance.setSslSocketFactory(sslSocketFactory); - httpsJkws.setSimpleHttpGet(getInstance); - - // The HttpsJwksVerificationKeyResolver uses JWKs obtained from the HttpsJwks and will select - // the most appropriate one to use for verification based on the Key ID and other factors - // provided in the header of the JWS/JWT. - HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = - new HttpsJwksVerificationKeyResolver(httpsJkws); - - // Use JwtConsumerBuilder to construct an appropriate JwtConsumer, which will - // be used to validate and process the JWT. - // The specific validation requirements for a JWT are context dependent, however, - // it typically advisable to require a (reasonable) expiration time, a trusted issuer, and - // and audience that identifies your system as the intended recipient. - // If the JWT is encrypted too, you need only provide a decryption key or - // decryption key resolver to the builder. - JwtConsumer jwtConsumer = - new JwtConsumerBuilder() - .setRequireExpirationTime() // the JWT must have an expiration time - .setAllowedClockSkewInSeconds( - 30) // allow some leeway in validating time based claims to account for clock skew - .setRequireSubject() // the JWT must have a subject claim - .setExpectedIssuer( - "https://daps.aisec.fraunhofer.de") // whom the JWT needs to have been issued by - .setExpectedAudience(targetAudience) // to whom the JWT is intended for - .setVerificationKeyResolver(httpsJwksKeyResolver) - .setJwsAlgorithmConstraints( // only allow the expected signature algorithm(s) in the - // given context - new org.jose4j.jwa.AlgorithmConstraints( - org.jose4j.jwa.AlgorithmConstraints.ConstraintType - .WHITELIST, // which is only RS256 here - AlgorithmIdentifiers.RSA_USING_SHA256)) - .build(); // create the JwtConsumer instance - - LOG.info("Verifying JWT..."); - // Validate the JWT and process it to the Claims - JwtClaims jwtClaims = jwtConsumer.processToClaims(dynamicAttributeToken); - LOG.info("JWT validation succeeded! " + jwtClaims); - - return jwtClaims.getClaimsMap(); - } catch (InvalidJwtException e) { - // InvalidJwtException will be thrown, if the JWT failed processing or validation in anyway. - // Hopefully with meaningful explanations(s) about what went wrong. - LOG.warn("Invalid JWT!", e); - - // Programmatic access to (some) specific reasons for JWT invalidity is also possible - // should you want different error handling behavior for certain conditions. - - // Whether or not the JWT has expired being one common reason for invalidity - if (e.hasExpired()) { - try { - LOG.warn("JWT expired at " + e.getJwtContext().getJwtClaims().getExpirationTime()); - } catch (MalformedClaimException e1) { - LOG.error("Malformed claim encountered", e1); - } - } - - // Or maybe the audience was invalid - if (e.hasErrorCode(ErrorCodes.AUDIENCE_INVALID)) { - try { - LOG.warn("JWT had wrong audience: " + e.getJwtContext().getJwtClaims().getAudience()); - } catch (MalformedClaimException e1) { - LOG.error("Malformed claim encountered", e1); - } - } - - throw e; - } - } - - @Override - @SuppressWarnings("unchecked") - public void validateDATSecurityAttributes(Map claims, ConnectionSettings connectionSettings) - throws DatException { - try { - Object idsAttributesObject = claims.get("ids_attributes"); - Map securityProfile; - if (idsAttributesObject instanceof Map) { - var securityProfileObject = ((Map) idsAttributesObject).get("security_profile"); - if (securityProfileObject instanceof Map) { - securityProfile = (Map) securityProfileObject; - } else { - throw new DatException("No security_profile found in claims " + securityProfileObject); - } - } else { - throw new DatException("No ids_attributes claims found in claims " + idsAttributesObject); - } - - // Validate audit_logging - var auditLogging = Integer.parseInt(securityProfile.get("audit_logging").toString()); - if (Integer.parseInt(connectionSettings.getAuditLogging()) > auditLogging) { - throw new DatException("Client does not support the security requirements for audit_logging."); - } - - // TODO: validate further security attributes - } catch (NumberFormatException e) { - throw new DatException("Connection settings contains an invalid number format.", e); - } - } - - @Activate - public void run() { - LOG.info("Token renewal triggered."); - try { - ConnectorConfig config = settings.getConnectorConfig(); - acquireToken( - FileSystems.getDefault().getPath("etc"), - config.getDapsUrl(), - config.getKeystoreName(), - config.getKeystorePassword(), - config.getKeystoreAliasName(), - config.getTruststoreName(), - config.getConnectorUUID()); - - } catch (Exception e) { - LOG.error("Token renewal failed", e); - } - } -} diff --git a/ids-webconsole/build.gradle b/ids-webconsole/build.gradle deleted file mode 100644 index 266e65e54..000000000 --- a/ids-webconsole/build.gradle +++ /dev/null @@ -1,144 +0,0 @@ -apply plugin: 'com.moowork.node' -apply plugin: 'com.benjaminsproule.swagger' - -description = 'IDS Core Platform Webconsole' - -sourceSets { - main { - // only include the OSGI blueprint and the built angular app - resources { - include 'OSGI-INF/blueprint/*' - } - } -} - -swagger { - apiSource { - springmvc = false - locations = [ 'de.fhg.aisec.ids.webconsole.api' ] - schemes = ['http'] - host = 'localhost:8181' - basePath = '/' - info { - title = 'Trusted Connector API' - version = project.version - license { - url = 'http://www.apache.org/licenses/LICENSE-2.0.html' - name = 'Apache 2.0' - } - description ='''This is the administrative REST API of the Trusted Connector. - -The API provides an administrative interface to manage the Trusted Connector at runtime -and is used by the default administration dashboard ("web console"). -''' - } - swaggerDirectory = "${project.projectDir}/generated/swagger-ui" - outputFormats = ['json','yaml'] - securityDefinition { - // `name` can be used refer to this security schemes from elsewhere - name = 'oauth2' - type = 'oauth2' - // The flow used by the OAuth2 security scheme - flow = 'password' - tokenUrl = 'https://localhost:8181/user/login' - scope { - name = 'write:api' - description = 'Read and write access to the API' - } - } - /* the plugin could theoretically also generate the html files, however it currently only allows - for the generation of html OR swagger.json, not both. Therefore we still need to use spectacle using yarn */ - // templatePath = "${project.projectDir}/src/test/resources/strapdown.html.hbs" - // outputPath = "${project.projectDir}/generated/document.html" - } -} - -dependencies { - providedByBundle(project(':ids-api')) { transitive = false } - - // Actual implementation must be provided by ids-infomodel-manager - compileOnly group: 'de.fraunhofer.iais.eis.ids.infomodel', name: 'java', version: libraryVersions.infomodel - - // Bill of Materials (BOM) for Camel - bom group: 'org.apache.camel', name: 'camel-parent', version: libraryVersions.camel - - providedByFeature group: 'javax.servlet', name: 'javax.servlet-api', version: libraryVersions.javaxServlet - - providedByFeature group: 'org.apache.camel', name: 'camel-core', version: libraryVersions.camel - providedByFeature group: 'org.apache.camel', name: 'camel-core-osgi', version: libraryVersions.camel - - providedByFeature group: 'org.apache.cxf', name: 'cxf-rt-frontend-jaxrs', version: libraryVersions.cxf - providedByFeature group: 'org.apache.cxf', name: 'cxf-rt-rs-extension-providers', version: libraryVersions.cxf - - // This is required for compilation only, and provided by karaf automatically, likely by some included feature - compileOnly group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: libraryVersions.wsRsApi - - compileOnly group: 'org.checkerframework', name: 'checker-qual', version: libraryVersions.checkerQual - - // use our specified version of jackson instead of the cxf-jackson feature - providedByBundle group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: libraryVersions.jackson - providedByBundle group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: libraryVersions.jackson - providedByBundle group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: libraryVersions.jackson - providedByBundle group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: libraryVersions.jackson - providedByBundle group: 'com.fasterxml.jackson.jaxrs', name: 'jackson-jaxrs-json-provider', version: libraryVersions.jackson - - providedByBundle group: 'org.bitbucket.b_c', name: 'jose4j', version: libraryVersions.jose4j - implementation group: 'com.auth0', name: 'java-jwt', version: libraryVersions.auth0Jwt - osgiCore group: 'org.apache.felix', name: 'org.apache.felix.framework', version: libraryVersions.felixFramework - osgiCore group: 'org.osgi', name: 'osgi.cmpn', version: libraryVersions.osgiCompendium - - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: libraryVersions.log4j - providedByBundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: libraryVersions.log4j - - compileOnly group: 'io.swagger', name: 'swagger-jaxrs', version: libraryVersions.swagger - - testImplementation group: 'junit', name: 'junit' - testImplementation group: 'org.mockito', name: 'mockito-core', version: libraryVersions.mockito - - testImplementation group: 'org.apache.cxf', name: 'cxf-rt-transports-local', version: libraryVersions.cxf - testImplementation group: 'org.apache.cxf', name: 'cxf-rt-rs-client', version: libraryVersions.cxf -} - -task yarnInstall(type: YarnTask) { - inputs.file('src/main/resources/www/package.json').withPathSensitivity(PathSensitivity.RELATIVE) - inputs.file('src/main/resources/www/yarn.lock').withPathSensitivity(PathSensitivity.RELATIVE) - outputs.dir('src/main/resources/www/node_modules') - outputs.cacheIf { true } - - workingDir = file('src/main/resources/www') - args = ['install', '--ignore-optional'] -} - -task yarnBuild(type: YarnTask) { - inputs.file('src/main/resources/www/package.json').withPathSensitivity(PathSensitivity.RELATIVE) - inputs.file('src/main/resources/www/yarn.lock').withPathSensitivity(PathSensitivity.RELATIVE) - inputs.file('src/main/resources/www/angular.json').withPathSensitivity(PathSensitivity.RELATIVE) - inputs.dir('src/main/resources/www/src').withPathSensitivity(PathSensitivity.RELATIVE) - outputs.dir('build/resources/main/www') - outputs.cacheIf { true } - - workingDir = file('src/main/resources/www') - args = ['bundle'] - onlyIf { !rootProject.hasProperty("skipAngular") } -} - -task yarnLint(type: YarnTask) { - inputs.file('src/main/resources/www/package.json').withPathSensitivity(PathSensitivity.RELATIVE) - inputs.file('src/main/resources/www/yarn.lock').withPathSensitivity(PathSensitivity.RELATIVE) - inputs.file('src/main/resources/www/tslint.json').withPathSensitivity(PathSensitivity.RELATIVE) - inputs.dir('src/main/resources/www/src').withPathSensitivity(PathSensitivity.RELATIVE) - outputs.upToDateWhen { true } - outputs.cacheIf { true } - - workingDir = file('src/main/resources/www') - args = ['lint'] - onlyIf { !rootProject.hasProperty("skipAngular") } -} - -yarnBuild.dependsOn(yarnLint) - -// make sure, yarn install is executed first -yarnBuild.dependsOn(yarnInstall) - -processResources.dependsOn(yarnBuild) - diff --git a/ids-webconsole/build.gradle.kts b/ids-webconsole/build.gradle.kts new file mode 100644 index 000000000..f8dc46d06 --- /dev/null +++ b/ids-webconsole/build.gradle.kts @@ -0,0 +1,150 @@ +import com.benjaminsproule.swagger.gradleplugin.model.* +import com.github.gradle.node.yarn.task.YarnTask + +@Suppress("UNCHECKED_CAST") +val libraryVersions = rootProject.extra.get("libraryVersions") as Map + +plugins { + id("com.github.node-gradle.node") version "3.0.1" + id("com.benjaminsproule.swagger") version "1.0.14" +} + +description = "IDS Core Platform Webconsole" + +sourceSets { + main { + // only include the OSGI blueprint and the built angular app + resources { + include("OSGI-INF/blueprint/*") + } + } +} + +swagger { + apiSource(closureOf { + springmvc = false + locations = listOf("de.fhg.aisec.ids.webconsole.api") + schemes = listOf("http") + host = "localhost:8181" + basePath = "/" + info(closureOf { + title = "Trusted Connector API" + version = project.version as String + license(closureOf { + url = "http://www.apache.org/licenses/LICENSE-2.0.html" + name = "Apache 2.0" + }) + description ="""This is the administrative REST API of the Trusted Connector. + +The API provides an administrative interface to manage the Trusted Connector at runtime +and is used by the default administration dashboard ("web console"). +""" + }) + swaggerDirectory = "${project.projectDir}/generated/swagger-ui" + outputFormats = listOf("json","yaml") + securityDefinition(closureOf { + // `name` can be used refer to this security schemes from elsewhere + name = "oauth2" + type = "oauth2" + // The flow used by the OAuth2 security scheme + flow = "password" + tokenUrl = "https://localhost:8181/user/login" + scope(closureOf { + name = "write:api" + description = "Read and write access to the API" + }) + }) + /* the plugin could theoretically also generate the html files, however it currently only allows + for the generation of html OR swagger.json, not both. Therefore we still need to use spectacle using yarn */ + // templatePath = "${project.projectDir}/src/test/resources/strapdown.html.hbs" + // outputPath = "${project.projectDir}/generated/document.html" + }) +} + +dependencies { + providedByBundle(project(":ids-api")) { isTransitive = false } + + // Actual implementation must be provided by ids-infomodel-manager + compileOnly("de.fraunhofer.iais.eis.ids.infomodel", "java", libraryVersions["infomodel"]) + + providedByFeature("javax.servlet", "javax.servlet-api", libraryVersions["javaxServlet"]) + + providedByFeature("org.apache.camel", "camel-core", libraryVersions["camel"]) + + providedByFeature("org.apache.cxf", "cxf-rt-frontend-jaxrs", libraryVersions["cxf"]) + providedByFeature("org.apache.cxf", "cxf-rt-rs-extension-providers", libraryVersions["cxf"]) + + // This is required for compilation only, and provided by karaf automatically, likely by some included feature + compileOnly("javax.ws.rs", "javax.ws.rs-api", libraryVersions["wsRsApi"]) + + compileOnly("org.checkerframework", "checker-qual", libraryVersions["checkerQual"]) + + // use our specified version of jackson instead of the cxf-jackson feature + providedByBundle("com.fasterxml.jackson.core", "jackson-core", libraryVersions["jackson"]) + providedByBundle("com.fasterxml.jackson.core", "jackson-databind", libraryVersions["jackson"]) + providedByBundle("com.fasterxml.jackson.core", "jackson-annotations", libraryVersions["jackson"]) + providedByBundle("com.fasterxml.jackson.dataformat", "jackson-dataformat-yaml", libraryVersions["jackson"]) + providedByBundle("com.fasterxml.jackson.jaxrs", "jackson-jaxrs-json-provider", libraryVersions["jackson"]) + + providedByBundle("org.bitbucket.b_c", "jose4j", libraryVersions["jose4j"]) + implementation("com.auth0", "java-jwt", libraryVersions["auth0Jwt"]) + osgiCore("org.apache.felix", "org.apache.felix.framework", libraryVersions["felixFramework"]) + osgiCore("org.osgi", "osgi.cmpn", libraryVersions["osgiCompendium"]) + + compileOnly("io.swagger", "swagger-jaxrs", libraryVersions["swagger"]) + + testImplementation("junit", "junit", libraryVersions["junit4"]) + testImplementation("org.mockito", "mockito-core", libraryVersions["mockito"]) + + testImplementation("org.apache.cxf", "cxf-rt-transports-local", libraryVersions["cxf"]) + testImplementation("org.apache.cxf", "cxf-rt-rs-client", libraryVersions["cxf"]) +} + +node { + download.set(true) +} + +val yarnInstall by tasks.registering(YarnTask::class) { + inputs.file("src/main/resources/www/package.json").withPathSensitivity(PathSensitivity.RELATIVE) + inputs.file("src/main/resources/www/yarn.lock").withPathSensitivity(PathSensitivity.RELATIVE) + outputs.dir("src/main/resources/www/node_modules") + outputs.cacheIf { true } + + workingDir.set(file("src/main/resources/www")) + yarnCommand.set(listOf("install", "--ignore-optional")) + onlyIf { !rootProject.hasProperty("skipAngular") } +} + +val yarnLint by tasks.registering(YarnTask::class) { + inputs.file("src/main/resources/www/package.json").withPathSensitivity(PathSensitivity.RELATIVE) + inputs.file("src/main/resources/www/yarn.lock").withPathSensitivity(PathSensitivity.RELATIVE) + inputs.file("src/main/resources/www/tslint.json").withPathSensitivity(PathSensitivity.RELATIVE) + inputs.dir("src/main/resources/www/src").withPathSensitivity(PathSensitivity.RELATIVE) + outputs.upToDateWhen { true } + outputs.cacheIf { true } + + workingDir.set(file("src/main/resources/www")) + yarnCommand.set(listOf("lint")) + onlyIf { !rootProject.hasProperty("skipAngular") } +} + +val yarnBuild by tasks.registering(YarnTask::class) { + inputs.file("src/main/resources/www/package.json").withPathSensitivity(PathSensitivity.RELATIVE) + inputs.file("src/main/resources/www/yarn.lock").withPathSensitivity(PathSensitivity.RELATIVE) + inputs.file("src/main/resources/www/angular.json").withPathSensitivity(PathSensitivity.RELATIVE) + inputs.dir("src/main/resources/www/src").withPathSensitivity(PathSensitivity.RELATIVE) + outputs.dir("build/resources/main/www") + outputs.cacheIf { true } + + workingDir.set(file("src/main/resources/www")) + yarnCommand.set(listOf("bundle")) + onlyIf { !rootProject.hasProperty("skipAngular") } + + dependsOn(yarnLint) + // make sure yarn install is executed first + dependsOn(yarnInstall) +} + +tasks.processResources { + dependsOn(yarnBuild) +} diff --git a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/WebConsoleComponent.java b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/WebConsoleComponent.java index 97e2997b7..29527f3f8 100644 --- a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/WebConsoleComponent.java +++ b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/WebConsoleComponent.java @@ -27,7 +27,6 @@ import de.fhg.aisec.ids.api.policy.PAP; import de.fhg.aisec.ids.api.router.RouteManager; import de.fhg.aisec.ids.api.settings.Settings; -import de.fhg.aisec.ids.api.tokenm.TokenManager; import org.checkerframework.checker.nullness.qual.Nullable; import org.osgi.service.component.annotations.*; @@ -51,9 +50,6 @@ public class WebConsoleComponent { @Reference(cardinality = ReferenceCardinality.OPTIONAL) private EndpointConfigManager dynEndConManager = null; - @Reference(cardinality = ReferenceCardinality.OPTIONAL) - private TokenManager tokenManager = null; - @Reference(cardinality = ReferenceCardinality.OPTIONAL) private Settings settings = null; @@ -116,15 +112,6 @@ public static ConnectionManager getConnectionManager() { return null; } - @Nullable - public static TokenManager getTokenManager() { - WebConsoleComponent in = instance; - if (in != null) { - return in.tokenManager; - } - return null; - } - @Nullable public static Settings getSettings() { WebConsoleComponent in = instance; diff --git a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/AppApi.java b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/AppApi.java index 84756c148..775f7ef2d 100644 --- a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/AppApi.java +++ b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/AppApi.java @@ -19,6 +19,7 @@ */ package de.fhg.aisec.ids.webconsole.api; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import de.fhg.aisec.ids.api.cm.ApplicationContainer; import de.fhg.aisec.ids.api.cm.ContainerManager; @@ -307,12 +308,12 @@ public List search(AppSearchRequest searchRequest) { } String url = settings.getConnectorConfig().getAppstoreUrl(); - String r = client.target(url).request(MediaType.TEXT_PLAIN).get(String.class); + String r = client.target(url).request(MediaType.APPLICATION_JSON).get(String.class); ObjectMapper mapper = new ObjectMapper(); - ApplicationContainer[] result = mapper.readValue(r, ApplicationContainer[].class); + List result = mapper.readValue(r, new TypeReference<>() {}); if (term != null && !term.equals("")) { - return Arrays.asList(result) + return result .parallelStream() .filter( app -> @@ -323,7 +324,7 @@ public List search(AppSearchRequest searchRequest) { || (app.getCategories() != null && app.getCategories().contains(term))) .collect(Collectors.toList()); } else { - return Arrays.asList(result); + return result; } } catch (IOException e) { throw new InternalServerErrorException(e); diff --git a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/CertApi.java b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/CertApi.java index f77c8bb19..9d9dc1d54 100644 --- a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/CertApi.java +++ b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/CertApi.java @@ -68,8 +68,8 @@ public class CertApi { private static final Logger LOG = LoggerFactory.getLogger(CertApi.class); private static final String KEYSTORE_PWD = "password"; - private static final String TRUSTSTORE_FILE = "client-truststore.jks"; - private static final String KEYSTORE_FILE = "client-keystore.jks"; + private static final String TRUSTSTORE_FILE = "truststore.p12"; + private static final String KEYSTORE_FILE = "provider-keystore.p12"; @GET @ApiOperation(value = "Starts ACME renewal over X509v3 certificates") diff --git a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/ConfigApi.java b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/ConfigApi.java index 40cdbc205..0eb4e5127 100644 --- a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/ConfigApi.java +++ b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/ConfigApi.java @@ -28,19 +28,17 @@ import de.fhg.aisec.ids.api.settings.ConnectionSettings; import de.fhg.aisec.ids.api.settings.ConnectorConfig; import de.fhg.aisec.ids.api.settings.Settings; -import de.fhg.aisec.ids.api.tokenm.TokenManager; import de.fhg.aisec.ids.webconsole.WebConsoleComponent; import io.swagger.annotations.*; -import java.nio.file.FileSystems; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import java.util.*; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; /** * REST API interface for configurations in the connector. @@ -94,23 +92,6 @@ public String set(ConnectorConfig config) { return "No settings available"; } settings.setConnectorConfig(config); - TokenManager tokenManager = WebConsoleComponent.getTokenManager(); - if (tokenManager == null) { - return "No TokenManager available"; - } - - try { - tokenManager.acquireToken( - FileSystems.getDefault().getPath("etc"), - config.getDapsUrl(), - config.getKeystoreName(), - config.getKeystorePassword(), - config.getKeystoreAliasName(), - config.getTruststoreName(), - config.getConnectorUUID()); - } catch (Exception e) { - e.printStackTrace(); - } return "OK"; } diff --git a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/RouteApi.java b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/RouteApi.java index 1d9297756..e947c0415 100644 --- a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/RouteApi.java +++ b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/RouteApi.java @@ -20,7 +20,6 @@ package de.fhg.aisec.ids.webconsole.api; import de.fhg.aisec.ids.api.Result; -import de.fhg.aisec.ids.api.internal.ComponentNotAvailableException; import de.fhg.aisec.ids.api.policy.PAP; import de.fhg.aisec.ids.api.router.*; import de.fhg.aisec.ids.webconsole.WebConsoleComponent; @@ -29,15 +28,16 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.Authorization; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * REST API interface for "data pipes" in the connector. @@ -92,7 +92,7 @@ public List list() { public RouteObject get(@ApiParam(value = "Route ID") @PathParam("id") @NonNull String id) { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } RouteObject oRoute = rm.getRoute(id); if (oRoute == null) { @@ -109,7 +109,7 @@ public RouteObject get(@ApiParam(value = "Route ID") @PathParam("id") @NonNull S public String getAsString(@ApiParam(value = "Route ID") @PathParam("id") String id) { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } String routeAsString = rm.getRouteAsString(id); if (routeAsString == null) { @@ -128,7 +128,7 @@ public Result startRoute(@PathParam("id") String id) { try { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } rm.startRoute(id); return new Result(); @@ -148,7 +148,7 @@ public Result saveRoute(@PathParam("id") @NonNull String id, @NonNull String rou try { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } rm.saveRoute(id, routeDefinition); return new Result(); @@ -168,7 +168,7 @@ public Result addRoute(@NonNull String routeDefinition) { try { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } rm.addRoute(routeDefinition); return new Result(); @@ -191,7 +191,7 @@ public Result stopRoute(@PathParam("id") String id) { try { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } rm.stopRoute(id); return new Result(); @@ -209,7 +209,7 @@ public Result stopRoute(@PathParam("id") String id) { public RouteMetrics getMetrics(@PathParam("id") String routeId) { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } return rm.getRouteMetrics().get(routeId); } @@ -225,7 +225,7 @@ public RouteMetrics getMetrics(@PathParam("id") String routeId) { public RouteMetrics getMetrics() { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } return aggregateMetrics(rm.getRouteMetrics().values()); } @@ -273,7 +273,7 @@ private RouteMetrics aggregateMetrics(Collection currentMetrics) { public List getComponents() { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } return rm.listComponents(); } @@ -285,7 +285,7 @@ public List getComponents() { public Map listEndpoints() { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } return rm.listEndpoints(); } @@ -297,9 +297,12 @@ public Map listEndpoints() { public ValidationInfo validate(@PathParam("routeId") String routeId) { PAP pap = WebConsoleComponent.getPolicyAdministrationPoint(); if (pap == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } RouteVerificationProof rvp = pap.verifyRoute(routeId); + if (rvp == null) { + throw new InternalServerErrorException(); + } ValidationInfo vi = new ValidationInfo(); vi.valid = rvp.isValid(); if (!rvp.isValid()) { @@ -315,7 +318,7 @@ public ValidationInfo validate(@PathParam("routeId") String routeId) { public String getRouteProlog(@PathParam("routeId") @NonNull String routeId) { RouteManager rm = WebConsoleComponent.getRouteManager(); if (rm == null) { - throw new ComponentNotAvailableException(); + throw new InternalServerErrorException(); } return rm.getRouteAsProlog(routeId); } diff --git a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/SettingsApi.java b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/SettingsApi.java index 22fb1c3de..605c31042 100644 --- a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/SettingsApi.java +++ b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/SettingsApi.java @@ -23,16 +23,17 @@ import de.fhg.aisec.ids.api.infomodel.InfoModel; import de.fhg.aisec.ids.webconsole.WebConsoleComponent; import de.fraunhofer.iais.eis.Connector; -import de.fraunhofer.iais.eis.util.PlainLiteral; +import de.fraunhofer.iais.eis.util.TypedLiteral; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.Authorization; -import java.util.stream.Collectors; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import java.util.stream.Collectors; + /** * REST API interface for Connector settings in the connector. * @@ -87,7 +88,7 @@ public ConnectorProfile getConnectorProfile() { c.getSecurityProfile(), c.getId(), c.getMaintainer(), - c.getDescription().stream().map(PlainLiteral.class::cast).collect(Collectors.toList())); + c.getDescription().stream().map(TypedLiteral.class::cast).collect(Collectors.toList())); } } @@ -99,7 +100,6 @@ public ConnectorProfile getConnectorProfile() { @Path("/selfInformation") @Produces("application/ld+json") // TODO Document ApiOperation - @AuthorizationRequired public String getSelfInformation() { InfoModel im = WebConsoleComponent.getInfoModelManager(); if (im == null) { diff --git a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/UserApi.java b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/UserApi.java index 3c6852799..44b4c3da2 100644 --- a/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/UserApi.java +++ b/ids-webconsole/src/main/java/de/fhg/aisec/ids/webconsole/api/UserApi.java @@ -19,22 +19,15 @@ */ package de.fhg.aisec.ids.webconsole.api; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; - import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import de.fhg.aisec.ids.webconsole.api.data.User; import io.swagger.annotations.Api; -import java.security.Key; -import java.security.NoSuchAlgorithmException; -import java.util.Calendar; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import javax.crypto.KeyGenerator; import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.Configuration; @@ -46,8 +39,15 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; @Path("/user") @Api(value = "User Authentication") @@ -98,7 +98,7 @@ public Response authenticateUser(User user) { private String issueToken(String username) { Calendar cal = Calendar.getInstance(); - cal.add(Calendar.DAY_OF_MONTH, 1); + cal.setTimeInMillis(cal.getTimeInMillis() + 86_400_000); Date tomorrow = cal.getTime(); return JWT.create() @@ -114,26 +114,23 @@ private boolean authenticate(String user, String password) throws LoginException can be configured as needed without changing this code here. */ if (Configuration.getConfiguration().getAppConfigurationEntry("karaf") == null) { - LOG.warn( - "No LoginModules configured for karaf. This is okay if running as unit test. If this message appears in Karaf container, make sure that JAAS is available."); + LOG.warn("No LoginModules configured for karaf. This is okay if running as unit test. " + + "If this message appears in Karaf container, make sure that JAAS is available."); return "ids".equals(user) && "ids".equals(password); } LoginContext ctx = new LoginContext( "karaf", - new CallbackHandler() { - @Override - public void handle(Callback[] callbacks) { - for (Callback cb : callbacks) { - if (cb instanceof PasswordCallback) { - ((PasswordCallback) cb).setPassword(password.toCharArray()); - } - if (cb instanceof NameCallback) { - ((NameCallback) cb).setName(user); + callbacks -> { + for (Callback cb : callbacks) { + if (cb instanceof PasswordCallback) { + ((PasswordCallback) cb).setPassword(password.toCharArray()); + } + if (cb instanceof NameCallback) { + ((NameCallback) cb).setName(user); + } } - } - } - }); + }); ctx.login(); return true; } diff --git a/ids-webconsole/src/main/resources/www/browserslist b/ids-webconsole/src/main/resources/www/.browserslistrc similarity index 100% rename from ids-webconsole/src/main/resources/www/browserslist rename to ids-webconsole/src/main/resources/www/.browserslistrc diff --git a/ids-webconsole/src/main/resources/www/package.json b/ids-webconsole/src/main/resources/www/package.json index d7f6d7976..0308263a9 100644 --- a/ids-webconsole/src/main/resources/www/package.json +++ b/ids-webconsole/src/main/resources/www/package.json @@ -11,39 +11,39 @@ }, "private": true, "dependencies": { - "@angular/animations": "~9.1.0", - "@angular/common": "~9.1.0", - "@angular/core": "~9.1.0", - "@angular/forms": "~9.1.0", - "@angular/platform-browser": "~9.1.0", - "@angular/platform-browser-dynamic": "~9.1.0", - "@angular/platform-server": "~9.1.0", - "@angular/router": "~9.1.0", + "@angular/animations": "~10.2.0", + "@angular/common": "~10.2.0", + "@angular/core": "~10.2.0", + "@angular/forms": "~10.2.0", + "@angular/platform-browser": "~10.2.0", + "@angular/platform-browser-dynamic": "~10.2.0", + "@angular/platform-server": "~10.2.0", + "@angular/router": "~10.2.0", "bootstrap": "^4.2.1", "core-js": "^3.6.4", "deep-equal": "^2.0.1", - "jquery": "^3.4.1", + "jquery": "^3.5.1", "material-design-lite": "^1.3.0", "ng2-ace-editor": "^0.3.9", "popper.js": "^1.16.1", "rxjs": "^6.5.2", "svg-pan-zoom": "^3.6.0", "topojson": "^3.0.2", - "tslib": "^1.10.0", + "tslib": "^2.0.0", "viz.js": "^2.1.1", "zone.js": "~0.10.2" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.901.0", - "@angular/cli": "~9.1.0", - "@angular/compiler": "~9.1.0", - "@angular/compiler-cli": "~9.1.0", + "@angular-devkit/build-angular": "~0.1002.0", + "@angular/cli": "~10.2.0", + "@angular/compiler": "~10.2.0", + "@angular/compiler-cli": "~10.2.0", "@saritasa/tslint-config-angular": "^2.0.0", "@types/node": "^12.11.1", "@types/vis": "^4.21.9", "codelyzer": "^5.1.2", - "tslint": "^5.12.1", - "typescript": "3.7.5", + "tslint": "~6.1.0", + "typescript": "4.0.5", "vis": "^4.20.0" } } diff --git a/ids-webconsole/src/main/resources/www/src/app/app.module.ts b/ids-webconsole/src/main/resources/www/src/app/app.module.ts index bd2f19474..0b106a0b9 100644 --- a/ids-webconsole/src/main/resources/www/src/app/app.module.ts +++ b/ids-webconsole/src/main/resources/www/src/app/app.module.ts @@ -13,7 +13,8 @@ import { HTTP_PROVIDER } from './application-http-client.service'; import { AppCardComponent } from './apps/app-card.component'; import { AppSearchResultCardComponent } from './apps/app-search-result-card.component'; import { AppService } from './apps/app.service'; -import { AppsComponent, AppsSearchComponent } from './apps/apps.component'; +import { AppsComponent } from './apps/apps.component'; +import { AppsSearchComponent } from './apps/apps-search.component'; import { ConfirmComponent } from './confirm/confirm.component'; import { ConfirmService } from './confirm/confirm.service'; import { ConnectionConfigurationComponent } from './connection-configuration/connection-configuration.component'; diff --git a/ids-webconsole/src/main/resources/www/src/app/app.routing.ts b/ids-webconsole/src/main/resources/www/src/app/app.routing.ts index 009379846..c61ccdebc 100644 --- a/ids-webconsole/src/main/resources/www/src/app/app.routing.ts +++ b/ids-webconsole/src/main/resources/www/src/app/app.routing.ts @@ -1,7 +1,8 @@ import { RouterModule, Routes } from '@angular/router'; import { AuthGuard } from './_guards/auth.guard'; -import { AppsComponent, AppsSearchComponent } from './apps/apps.component'; +import { AppsComponent } from './apps/apps.component'; +import { AppsSearchComponent } from './apps/apps-search.component'; import { ConnectionConfigurationComponent } from './connection-configuration/connection-configuration.component'; import { ConnectionReportComponent } from './connection-report/connection-report.component'; import { DashboardComponent } from './dashboard/dashboard.component'; diff --git a/ids-webconsole/src/main/resources/www/src/app/application-http-client.service.ts b/ids-webconsole/src/main/resources/www/src/app/application-http-client.service.ts index 912feeb82..2d04b6f92 100644 --- a/ids-webconsole/src/main/resources/www/src/app/application-http-client.service.ts +++ b/ids-webconsole/src/main/resources/www/src/app/application-http-client.service.ts @@ -7,11 +7,11 @@ import { environment } from '../environments/environment'; export interface RequestOptions { headers?: HttpHeaders | { - [header: string]: string | Array; + [header: string]: string | string[]; }; observe?: 'body'; params?: HttpParams | { - [param: string]: string | Array; + [param: string]: string | string[]; }; reportProgress?: boolean; responseType?: 'json' | 'text'; @@ -51,7 +51,7 @@ export interface ApplicationHttpClient { * @param params Body of the request * @param options Options of the request like headers, body, etc. */ - put(endPoint: string, params: Object, options?: RequestOptions): Observable; + put(endPoint: string, params: object, options?: RequestOptions): Observable; /** * DELETE request @@ -105,7 +105,7 @@ export class ApplicationHttpClientImpl implements ApplicationHttpClient { * @param params Body of the request * @param options Options of the request like headers, body, etc. */ - public put(endPoint: string, params: Object, options?: any): any { + public put(endPoint: string, params: object, options?: any): any { return this.http.put(environment.apiURL + endPoint, params, options); } diff --git a/ids-webconsole/src/main/resources/www/src/app/apps/app-card.component.ts b/ids-webconsole/src/main/resources/www/src/app/apps/app-card.component.ts index 4c292faf4..64d80b8f6 100644 --- a/ids-webconsole/src/main/resources/www/src/app/apps/app-card.component.ts +++ b/ids-webconsole/src/main/resources/www/src/app/apps/app-card.component.ts @@ -14,12 +14,12 @@ export class AppCardComponent implements OnInit { @Input() public app: App; public statusIcon: string; public statusColor: string; - private portDefs: Array; + private portDefs: PortDef[]; constructor(private readonly appService: AppService, private readonly appsComponent: AppsComponent) { } // the linter forces to mark 'appsComponent' as readonly which could be misleading; see method 'onDeleteBtnClick' below - get ports(): Array { + get ports(): PortDef[] { if (!this.portDefs) { this.portDefs = this.app.ports .map(list => list.split(',') diff --git a/ids-webconsole/src/main/resources/www/src/app/apps/app.service.ts b/ids-webconsole/src/main/resources/www/src/app/apps/app.service.ts index 1abe7d1f0..f3e10f6c1 100644 --- a/ids-webconsole/src/main/resources/www/src/app/apps/app.service.ts +++ b/ids-webconsole/src/main/resources/www/src/app/apps/app.service.ts @@ -15,8 +15,8 @@ export class AppService { constructor(private readonly http: HttpClient) { } - public getApps(): Observable> { - return this.http.get>(environment.apiURL + '/app/list/'); + public getApps(): Observable { + return this.http.get(environment.apiURL + '/app/list/'); } public stopApp(appId: string): Observable { @@ -48,11 +48,11 @@ export class AppService { return this.http.get(environment.apiURL + '/app/cml_version'); } - public searchApps(term: string): Observable> { + public searchApps(term: string): Observable { const headers = new HttpHeaders({ 'Content-Type': 'application/json' }); const searchTerm = new AppSearchTerm(); searchTerm.searchTerm = term; - const result = this.http.post>(environment.apiURL + '/app/search', + const result = this.http.post(environment.apiURL + '/app/search', searchTerm, {headers}); return result; diff --git a/ids-webconsole/src/main/resources/www/src/app/apps/app.ts b/ids-webconsole/src/main/resources/www/src/app/apps/app.ts index 421dd8070..12438cc02 100644 --- a/ids-webconsole/src/main/resources/www/src/app/apps/app.ts +++ b/ids-webconsole/src/main/resources/www/src/app/apps/app.ts @@ -10,8 +10,8 @@ export interface App { uptime: string; signature: string; owner: string; - labels: Array>; - ports: Array; + labels: Map[]; + ports: string[]; // Further portainer attributes: repository: any; @@ -21,17 +21,17 @@ export interface App { title: string; description: string; note: string; - categories: Array; + categories: string[]; platform: string; logo: string; registry: string; command: string; network: string; - env: Array>; + env: Map[]; privileged: boolean; interactive: boolean; restartPolicy: string; - volumes: Array; + volumes: any[]; } export class AppSearchTerm { diff --git a/ids-webconsole/src/main/resources/www/src/app/apps/apps-search.component.ts b/ids-webconsole/src/main/resources/www/src/app/apps/apps-search.component.ts new file mode 100644 index 000000000..3d5c56d24 --- /dev/null +++ b/ids-webconsole/src/main/resources/www/src/app/apps/apps-search.component.ts @@ -0,0 +1,45 @@ +import { AfterViewInit, Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; + +import { App } from './app'; +import { AppService } from './app.service'; + +declare var componentHandler: any; + +@Component({ + templateUrl: './apps-search.component.html', + providers: [] +}) +export class AppsSearchComponent implements OnInit, AfterViewInit { + public myForm: FormGroup; + public submitted: boolean; + public saved: boolean; + public searchResults: App[] = []; + + constructor(private readonly _fb: FormBuilder, private readonly _appService: AppService) { + this.saved = true; + this.submitted = false; + } + + public ngOnInit(): void { + // the short way + this.myForm = this._fb.group({ + apps_search: ['', [Validators.required as any, Validators.minLength(3) as any]] + }); + } + + public ngAfterViewInit(): void { + componentHandler.upgradeAllRegistered(); + } + + public save(model: any, isValid: boolean): void { + this.submitted = true; + this._appService + .searchApps(model.apps_search) + .subscribe(res => { this.searchResults = res; }); + } + + public trackApps(index: number, item: App): string { + return item.id; + } +} diff --git a/ids-webconsole/src/main/resources/www/src/app/apps/apps.component.ts b/ids-webconsole/src/main/resources/www/src/app/apps/apps.component.ts index 8b4c4b878..d389fe062 100644 --- a/ids-webconsole/src/main/resources/www/src/app/apps/apps.component.ts +++ b/ids-webconsole/src/main/resources/www/src/app/apps/apps.component.ts @@ -1,5 +1,4 @@ -import { AfterViewInit, Component, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { AfterViewInit, Component } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { App } from './app'; @@ -12,7 +11,7 @@ declare var componentHandler: any; providers: [] }) export class AppsComponent implements AfterViewInit { - public apps: Array; + public apps: App[]; constructor(private readonly appService: AppService, private readonly titleService: Title) { this.titleService.setTitle('Apps'); @@ -31,41 +30,3 @@ export class AppsComponent implements AfterViewInit { return item.id; } } - -@Component({ - templateUrl: './apps-search.component.html', - providers: [] -}) -export class AppsSearchComponent implements OnInit, AfterViewInit { - public myForm: FormGroup; - public submitted: boolean; - public saved: boolean; - public searchResults: Array = []; - - constructor(private readonly _fb: FormBuilder, private readonly _appService: AppService) { - this.saved = true; - this.submitted = false; - } - - public ngOnInit(): void { - // the short way - this.myForm = this._fb.group({ - apps_search: ['', [Validators.required as any, Validators.minLength(3) as any]] - }); - } - - public ngAfterViewInit(): void { - componentHandler.upgradeAllRegistered(); - } - - public save(model: any, isValid: boolean): void { - this.submitted = true; - this._appService - .searchApps(model.apps_search) - .subscribe(res => { this.searchResults = res; }); - } - - public trackApps(index: number, item: App): string { - return item.id; - } -} diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/configuration.ts b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/configuration.ts index 7851c8738..731992e41 100644 --- a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/configuration.ts +++ b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/configuration.ts @@ -11,14 +11,7 @@ export class Configuration { this.settings = settings; } else { this.settings = { - integrityProtectionAndVerification: '1', - authentication: '1', - serviceIsolation: '1', - integrityProtectionVerificationScope: '1', - appExecutionResources: '1', - dataUsageControlSupport: '1', - auditLogging: '1', - localDataConfidentiality: '1' + securityProfile: 'idsc:BASE_CONNECTOR_SECURITY_PROFILE' }; } } diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.component.html b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.component.html index 17cd095cf..237d95f37 100644 --- a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.component.html +++ b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.component.html @@ -27,72 +27,26 @@

Endpoint Security Requirements

Loading Settings...

- + @@ -100,281 +54,25 @@
Authentication
- + [(ngModel)]="model.settings.securityProfile" + name="securityProfile" + [value]="'idsc:BASE_CONNECTOR_SECURITY_PROFILE'" [checked]="model.settings.securityProfile === 'idsc:BASE_CONNECTOR_SECURITY_PROFILE'"/> + - + [(ngModel)]="model.settings.securityProfile" + name="securityProfile" + [value]="'idsc:TRUSTED_CONNECTOR_SECURITY_PROFILE'" [checked]="model.settings.securityProfile === 'idsc:TRUSTED_CONNECTOR_SECURITY_PROFILE'"/> + - + [(ngModel)]="model.settings.securityProfile" + name="securityProfile" + [value]="'idsc:TRUSTED_CONNECTOR_PLUS_SECURITY_PROFILE'" [checked]="model.settings.securityProfile === 'idsc:TRUSTED_CONNECTOR_PLUS_SECURITY_PROFILE'"/> +
- - - - - - - - - - - - - - - - - - - - -
-
Authentication
+
Required Security Profile
  • - None - No endpoint authentication required. Connections are encrypted, but authenticity of the communication partner cannot be guaranteed. Data may be sent to malicious endpoints. + BASE Security Profile + BASE security profile required. Lower security requirements for incoming connection requests.
  • - Server Authentication - Authenticity of the server must be guaranteed. Authenticity of the client is not checked. + TRUST Security Profile + TRUST security profile required. High security requirments for incoming connection requests.
  • - Mutual Authentication - Authenticity of server and client must be guaranteed. + TRUST+ Security Profile + TRUST+ security profile required. Highest security requirments for incoming connection requests.
-
App Isolation
-
    -
  • - - None - Apps are not isolated. A malicious app may compromise the whole connector. - -
  • -
  • - - Containers - Apps run in separate containers but may still communicate with each other and the Internet. - -
  • - - Trusted Containers - Apps run in separate, signed and restricted containers. By default, they may only communicate with the Core Platform which enforces usage control policies. - -
-
-
-
- - - - - - -
-
-
-
Attestation Scope
-
    -
  • - - None - Integrity of the remote connector is not attested. There will be no guarantees about the software stack running on a remote connector. Any data sent to the remote connector must be considered unprotected. - -
  • -
  • - - Kernel & Core Platform - Integrity of the remote connector's kernel and Core Platform will be attested. These components will be guaranteed to be in a known state, but apps remain unattested. - -
  • - - Full Stack - Integrity of the remote connector's kernel, Core Platform, and apps will be attested. All these components will be guaranteed to be in a known state. - -
-
-
-
- - - - - - -
-
-
-
Data Usage Control
-
    -
  • - - None - Remote connector is not expected to provide usage control. - -
  • -
  • - - Compliance - Remote connector is expected to apply usage control policies, but not to strictly enforce them at a technical level. Legal usage obligations may still apply - -
  • - - Enforcement - Remote connector must be able to technically enforce usage control policies. This requires a trusted remote platform. - -
-
-
-
- - - - - - -
-
-
-
Audit Logging
-
    -
  • - - None - No audit logging. - -
  • -
  • - - Local - Local audit logging. - -
  • - - Remote Ledger - Non-repudiatable audit logging in a remote ledger. - -
-
-
-
- - - - - - -
-
-
-
Local data protection
-
    -
  • - - None - Data is stored without additional protection. Administrators or malicious users may be able to read/modify/delete stored data. - -
  • -
  • - - Secure data erasure - Locally stored data may be securely erased. Administrators or malicious users may still be able to read/modify/delete stored data. - -
  • - - Full Disk Encryption - Local data is stored on a full disk encryption (FDE) medium. - -
-
-
-
- - - - - - -
-
-
diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.component.ts b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.component.ts index 3c2a81661..44c8189fc 100644 --- a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.component.ts +++ b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.component.ts @@ -10,7 +10,7 @@ import { ConnectionConfigurationService } from './connection-configuration.servi styleUrls: ['./connection-configuration.component.css'] }) export class ConnectionConfigurationComponent implements OnInit { - public models: Array; + public models: Configuration[]; private _model?: Configuration; private _selectedIndex = 0; diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.service.ts b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.service.ts index f63a47645..d1504b34f 100644 --- a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.service.ts +++ b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/connection-configuration.service.ts @@ -25,7 +25,7 @@ export class ConnectionConfigurationService { .pipe(map(res => new Configuration(connection, res))); } - public getAllConfiguration(): Observable> { + public getAllConfiguration(): Observable { return this.http.get(environment.apiURL + '/config/connectionConfigs') .pipe(map(configMap => Object.keys(configMap) .map(key => new Configuration(key, configMap[key])))); diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/settings.interface.ts b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/settings.interface.ts index f6455eb84..7f146dd74 100644 --- a/ids-webconsole/src/main/resources/www/src/app/connection-configuration/settings.interface.ts +++ b/ids-webconsole/src/main/resources/www/src/app/connection-configuration/settings.interface.ts @@ -1,10 +1,3 @@ export interface Settings { - integrityProtectionAndVerification: string; - authentication: string; - serviceIsolation: string; - integrityProtectionVerificationScope: string; - appExecutionResources: string; - dataUsageControlSupport: string; - auditLogging: string; - localDataConfidentiality: string; + securityProfile: string; } diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-report/connection-report.component.ts b/ids-webconsole/src/main/resources/www/src/app/connection-report/connection-report.component.ts index 24b215c31..93515e4e0 100644 --- a/ids-webconsole/src/main/resources/www/src/app/connection-report/connection-report.component.ts +++ b/ids-webconsole/src/main/resources/www/src/app/connection-report/connection-report.component.ts @@ -3,7 +3,9 @@ import { Title } from '@angular/platform-browser'; import { delay, retryWhen, take } from 'rxjs/operators'; import { ConnectionReportService } from './connection-report.service'; -import { Endpoint, IncomingConnection, OutgoingConnection } from './connections'; +import { Endpoint } from './endpoint'; +import { IncomingConnection } from './incoming-connection'; +import { OutgoingConnection } from './outgoing-connection'; @Component({ selector: 'connections', @@ -12,9 +14,9 @@ import { Endpoint, IncomingConnection, OutgoingConnection } from './connections' }) export class ConnectionReportComponent implements OnInit { - public incomingConnections: Array; - public outgoingConnections: Array; - public endpoints: Array; + public incomingConnections: IncomingConnection[]; + public outgoingConnections: OutgoingConnection[]; + public endpoints: Endpoint[]; constructor(private readonly titleService: Title, private readonly connectionService: ConnectionReportService) { this.titleService.setTitle('IDS Connections'); diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-report/connection-report.service.ts b/ids-webconsole/src/main/resources/www/src/app/connection-report/connection-report.service.ts index 5d1ac4861..9d8fc3d5a 100644 --- a/ids-webconsole/src/main/resources/www/src/app/connection-report/connection-report.service.ts +++ b/ids-webconsole/src/main/resources/www/src/app/connection-report/connection-report.service.ts @@ -4,23 +4,25 @@ import { Observable } from 'rxjs'; import { environment } from '../../environments/environment'; -import { Endpoint, IncomingConnection, OutgoingConnection } from './connections'; +import { Endpoint } from './endpoint'; +import { IncomingConnection } from './incoming-connection'; +import { OutgoingConnection } from './outgoing-connection'; @Injectable() export class ConnectionReportService { constructor(private readonly http: HttpClient) { } - public getEndpoints(): Observable> { - return this.http.get>(environment.apiURL + '/connections/endpoints'); + public getEndpoints(): Observable { + return this.http.get(environment.apiURL + '/connections/endpoints'); } - public getIncomingConnections(): Observable> { - return this.http.get>(environment.apiURL + '/connections/incoming'); + public getIncomingConnections(): Observable { + return this.http.get(environment.apiURL + '/connections/incoming'); } - public getOutgoingConnections(): Observable> { - return this.http.get>(environment.apiURL + '/connections/outgoing'); + public getOutgoingConnections(): Observable { + return this.http.get(environment.apiURL + '/connections/outgoing'); } } diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-report/connections.ts b/ids-webconsole/src/main/resources/www/src/app/connection-report/connections.ts deleted file mode 100644 index a2c29b41b..000000000 --- a/ids-webconsole/src/main/resources/www/src/app/connection-report/connections.ts +++ /dev/null @@ -1,20 +0,0 @@ -export class IncomingConnection { - public endpointIdentifier: string; - public attestationResult: string; - public connectionKey: string; - public remoteHostName: string; -} - -export class OutgoingConnection { - public endpointIdentifier: string; - public remoteAuthentication: string; - public remoteIdentity: string; - public attestationResult: string; -} - -export class Endpoint { - public endpointIdentifier: string; - public defaultProtocol: string; - public port: string; - public host: string; -} diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-report/endpoint.ts b/ids-webconsole/src/main/resources/www/src/app/connection-report/endpoint.ts new file mode 100644 index 000000000..90fda1680 --- /dev/null +++ b/ids-webconsole/src/main/resources/www/src/app/connection-report/endpoint.ts @@ -0,0 +1,6 @@ +export class Endpoint { + public endpointIdentifier: string; + public defaultProtocol: string; + public port: string; + public host: string; +} diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-report/incoming-connection.ts b/ids-webconsole/src/main/resources/www/src/app/connection-report/incoming-connection.ts new file mode 100644 index 000000000..bec3642da --- /dev/null +++ b/ids-webconsole/src/main/resources/www/src/app/connection-report/incoming-connection.ts @@ -0,0 +1,6 @@ +export class IncomingConnection { + public endpointIdentifier: string; + public attestationResult: string; + public connectionKey: string; + public remoteHostName: string; +} diff --git a/ids-webconsole/src/main/resources/www/src/app/connection-report/outgoing-connection.ts b/ids-webconsole/src/main/resources/www/src/app/connection-report/outgoing-connection.ts new file mode 100644 index 000000000..3d6816cc1 --- /dev/null +++ b/ids-webconsole/src/main/resources/www/src/app/connection-report/outgoing-connection.ts @@ -0,0 +1,6 @@ +export class OutgoingConnection { + public endpointIdentifier: string; + public remoteAuthentication: string; + public remoteIdentity: string; + public attestationResult: string; +} diff --git a/ids-webconsole/src/main/resources/www/src/app/dashboard/dashboard.component.ts b/ids-webconsole/src/main/resources/www/src/app/dashboard/dashboard.component.ts index ec479ed09..fdf5ef54b 100644 --- a/ids-webconsole/src/main/resources/www/src/app/dashboard/dashboard.component.ts +++ b/ids-webconsole/src/main/resources/www/src/app/dashboard/dashboard.component.ts @@ -7,23 +7,21 @@ import { PolicyService } from '../dataflowpolicies/policy.service'; import { MetricService } from '../metric/metric.service'; import { RouteComponent } from '../routes/route'; import { RouteService } from '../routes/route.service'; -import { SubscriptionComponent } from '../subscription.component'; @Component({ templateUrl: './dashboard.component.html', providers: [] }) -export class DashboardComponent extends SubscriptionComponent implements OnInit { +export class DashboardComponent implements OnInit { @Output() public readonly changeTitle = new EventEmitter(); - public camelComponents: Array; - public apps: Array; + public camelComponents: RouteComponent[]; + public apps: App[]; public cmlVersion: string; public policies = 0; - public metric: Array = []; + public metric: string[] = []; constructor(private readonly titleService: Title, private readonly appService: AppService, private readonly routeService: RouteService, private readonly policyService: PolicyService, private readonly metricService: MetricService) { - super(); this.titleService.setTitle('Overview'); this.appService.getApps() diff --git a/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/dataflowpolicies.component.ts b/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/dataflowpolicies.component.ts index 10cadf5b1..26f3db884 100644 --- a/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/dataflowpolicies.component.ts +++ b/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/dataflowpolicies.component.ts @@ -10,7 +10,7 @@ declare var componentHandler: any; }) export class DataflowPoliciesComponent implements OnInit, AfterViewInit { @Output() public readonly changeTitle = new EventEmitter(); - private _policies?: Array; + private _policies?: string[]; private _isLoaded = false; constructor(private readonly titleService: Title, private readonly policyService: PolicyService) { @@ -31,7 +31,7 @@ export class DataflowPoliciesComponent implements OnInit, AfterViewInit { componentHandler.upgradeAllRegistered(); } - get policies(): Array { + get policies(): string[] { return this._policies; } diff --git a/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/dataflowpoliciesnew.component.ts b/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/dataflowpoliciesnew.component.ts index 827625432..cf0560753 100644 --- a/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/dataflowpoliciesnew.component.ts +++ b/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/dataflowpoliciesnew.component.ts @@ -13,7 +13,7 @@ export class NewDataflowPolicyComponent implements OnInit { public myForm: FormGroup; public data: Policy; public policyFileLabel = 'Select lucon file ...'; - public events: Array = []; + public events: any[] = []; public multiple: false; public fileUpload: AbstractControl; diff --git a/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/policy.service.ts b/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/policy.service.ts index 299203be5..2bf044a5d 100644 --- a/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/policy.service.ts +++ b/ids-webconsole/src/main/resources/www/src/app/dataflowpolicies/policy.service.ts @@ -11,8 +11,8 @@ import { Policy } from './policy.interface'; export class PolicyService { constructor(private readonly http: HttpClient) { } - public getPolicies(): Observable> { - return this.http.get>(environment.apiURL + '/policies/list'); + public getPolicies(): Observable { + return this.http.get(environment.apiURL + '/policies/list'); } // Installs a LUCON policy through the PAP diff --git a/ids-webconsole/src/main/resources/www/src/app/ids/ids.component.html b/ids-webconsole/src/main/resources/www/src/app/ids/ids.component.html index 1650937a8..dfd31343f 100644 --- a/ids-webconsole/src/main/resources/www/src/app/ids/ids.component.html +++ b/ids-webconsole/src/main/resources/www/src/app/ids/ids.component.html @@ -116,13 +116,6 @@

Settings

Valid truststore name required -
- - - Valid UUID required -
-