Skip to content

Commit

Permalink
Extracion of crypto-pgp and making crypto work on FIPS
Browse files Browse the repository at this point in the history
  • Loading branch information
JiriOndrusek authored and ppalaga committed Aug 12, 2024
1 parent 35c3eed commit ed8156c
Show file tree
Hide file tree
Showing 39 changed files with 1,025 additions and 129 deletions.
13 changes: 13 additions & 0 deletions catalog/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,19 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-crypto-pgp</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-csimple</artifactId>
Expand Down
13 changes: 13 additions & 0 deletions docs/modules/ROOT/examples/dataformats/pgp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Do not edit directly!
# This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page
cqArtifactId: camel-quarkus-crypto-pgp
cqArtifactIdBase: crypto-pgp
cqNativeSupported: true
cqStatus: Stable
cqDeprecated: false
cqJvmSince: 3.13.0
cqNativeSince: 3.13.0
cqCamelPartName: pgp
cqCamelPartTitle: PGP
cqCamelPartDescription: Encrypt and decrypt messages using Java Cryptographic Extension (JCE) and PGP.
cqExtensionPageTitle: PGP
1 change: 1 addition & 0 deletions docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@
*** xref:reference/extensions/opentelemetry.adoc[OpenTelemetry]
*** xref:reference/extensions/optaplanner.adoc[OptaPlanner]
*** xref:reference/extensions/pdf.adoc[PDF]
*** xref:reference/extensions/crypto-pgp.adoc[PGP]
*** xref:reference/extensions/paho.adoc[Paho]
*** xref:reference/extensions/paho-mqtt5.adoc[Paho MQTT5]
*** xref:reference/extensions/pinecone.adoc[Pinecone]
Expand Down
55 changes: 55 additions & 0 deletions docs/modules/ROOT/pages/reference/extensions/crypto-pgp.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Do not edit directly!
// This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page
[id="extensions-crypto-pgp"]
= PGP
:linkattrs:
:cq-artifact-id: camel-quarkus-crypto-pgp
:cq-native-supported: true
:cq-status: Stable
:cq-status-deprecation: Stable
:cq-description: Encrypt and decrypt messages using Bouncy Castle OpenPGP API.
:cq-deprecated: false
:cq-jvm-since: 3.13.0
:cq-native-since: 3.13.0

ifeval::[{doc-show-badges} == true]
[.badges]
[.badge-key]##JVM since##[.badge-supported]##3.13.0## [.badge-key]##Native since##[.badge-supported]##3.13.0##
endif::[]

Encrypt and decrypt messages using Bouncy Castle OpenPGP API.

[id="extensions-crypto-pgp-whats-inside"]
== What's inside

* xref:{cq-camel-components}:dataformats:pgp-dataformat.adoc[PGP data format]

Please refer to the above link for usage and configuration details.

[id="extensions-crypto-pgp-maven-coordinates"]
== Maven coordinates

https://{link-quarkus-code-generator}/?extension-search=camel-quarkus-crypto-pgp[Create a new project with this extension on {link-quarkus-code-generator}, window="_blank"]

Or add the coordinates to your existing project:

[source,xml]
----
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-crypto-pgp</artifactId>
</dependency>
----
ifeval::[{doc-show-user-guide-link} == true]
Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.
endif::[]

[id="extensions-crypto-pgp-camel-quarkus-limitations"]
== Camel Quarkus limitations

[id="extensions-crypto-pgp-limitations-fips"]
=== FIPS

It may not be possible to run `crypto` and `crypto-pgp` extensions together on FIPS enabled system.
For example if `crypto` uses `BCFIPS` provider and `crypto-pgp` uses `BC` provider, it is not possible to have both providers on one classpath.

42 changes: 42 additions & 0 deletions docs/modules/ROOT/pages/reference/extensions/crypto.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,48 @@ ifeval::[{doc-show-user-guide-link} == true]
Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.
endif::[]

[id="extensions-crypto-usage"]
== Usage
[id="extensions-crypto-usage-security-provider"]
=== Security Provider

Extension requires BouncyCastle provider and also utilizes the quarkus security extension (see https://quarkus.io/guides/security-customization#registering-security-providers[security providers registration doc])
If there is no `BC*` provider registered (by `quarkus.security.security-providers` property).
The `BC` provider is registered.

[id="extensions-crypto-usage-fips"]
=== FIPS

When running the `crypto` extension on FIPS enabled system any FIPS-compliant Java Security Provider (such as BCFIPS) has to be used.

* In the case of BCFIPS, please add BCFIPS dependency and `quarkus-security` (see the https://quarkus.io/guides/security-customization#bouncy-castle-fips[guide] for more information)
```
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bc-fips</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security</artifactId>
</dependency>
```
and register BCFIPS provider with following proprerty:
```
quarkus.security.security-providers=BCFIPS
```
* Alternatively, you can add different FIPS compliant provider. Make Sure that the provider is registered.





[id="extensions-crypto-camel-quarkus-limitations"]
== Camel Quarkus limitations





[id="extensions-crypto-ssl-in-native-mode"]
== SSL in native mode

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,45 @@
*/
package org.apache.camel.quarkus.support.bouncycastle.deployment;

import java.util.Collections;
import java.util.List;
import java.util.function.BooleanSupplier;
import java.util.stream.Collectors;

import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem;
import io.quarkus.security.deployment.BouncyCastleProviderBuildItem;
import io.quarkus.security.deployment.SecurityConfig;
import org.apache.camel.quarkus.support.bouncycastle.BouncyCastleRecorder;
import org.jboss.jandex.IndexView;

public class BouncyCastleSupportProcessor {

@BuildStep
SecurityConfig securityConfig;

@BuildStep(onlyIfNot = BcProviderConfigured.class)
void produceBouncyCastleProvider(BuildProducer<BouncyCastleProviderBuildItem> bouncyCastleProvider) {
//register BC if there is no BC or BCFIPS provider in securityConfiguration
bouncyCastleProvider.produce(new BouncyCastleProviderBuildItem());
}

@BuildStep
@BuildStep()
@Record(ExecutionTime.STATIC_INIT)
public void registerBouncyCastleProvider(List<CipherTransformationBuildItem> cipherTransformations,
BouncyCastleRecorder recorder,
ShutdownContextBuildItem shutdownContextBuildItem) {
List<String> allCipherTransformations = cipherTransformations.stream()
.flatMap(c -> c.getCipherTransformations().stream()).collect(Collectors.toList());
recorder.registerBouncyCastleProvider(allCipherTransformations, shutdownContextBuildItem);
}

@BuildStep()
ReflectiveClassBuildItem registerForReflection(CombinedIndexBuildItem combinedIndex) {
IndexView index = combinedIndex.getIndex();

Expand All @@ -54,23 +69,36 @@ ReflectiveClassBuildItem registerForReflection(CombinedIndexBuildItem combinedIn
return ReflectiveClassBuildItem.builder(dtos).build();
}

@BuildStep
IndexDependencyBuildItem registerBCDependencyForIndex() {
return new IndexDependencyBuildItem("org.bouncycastle", "bcprov-jdk18on");
}

@BuildStep
@BuildStep(onlyIfNot = FipsProviderConfigured.class)
void secureRandomConfiguration(BuildProducer<RuntimeReinitializedClassBuildItem> reinitialized) {
reinitialized.produce(new RuntimeReinitializedClassBuildItem("java.security.SecureRandom"));
}

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
public void registerBouncyCastleProvider(List<CipherTransformationBuildItem> cipherTransformations,
BouncyCastleRecorder recorder,
ShutdownContextBuildItem shutdownContextBuildItem) {
List<String> allCipherTransformations = cipherTransformations.stream()
.flatMap(c -> c.getCipherTransformations().stream()).collect(Collectors.toList());
recorder.registerBouncyCastleProvider(allCipherTransformations, shutdownContextBuildItem);
/**
* Indicates whether FIPS provider is registered via quarkus.security.
*/
static final class FipsProviderConfigured implements BooleanSupplier {
SecurityConfig securityConfig;

@Override
public boolean getAsBoolean() {
return securityConfig.securityProviders().orElse(Collections.emptySet()).stream()
.anyMatch(p -> p.toLowerCase().contains("fips"));

}
}

/**
* Indicates whether BC* provider is registered via quarkus.security.
*/
static final class BcProviderConfigured implements BooleanSupplier {
SecurityConfig securityConfig;

@Override
public boolean getAsBoolean() {
return securityConfig.securityProviders().orElse(Collections.emptySet()).stream()
.filter(p -> p.toLowerCase().startsWith("bc")).findAny().isPresent();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.apache.camel.quarkus.support.bouncycastle;

import java.lang.reflect.InvocationTargetException;
import java.security.Provider;
import java.security.Security;
import java.util.List;
Expand All @@ -25,7 +26,6 @@
import io.quarkus.runtime.ShutdownContext;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.security.runtime.SecurityProviderUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jboss.logging.Logger;

@Recorder
Expand All @@ -35,11 +35,30 @@ public class BouncyCastleRecorder {

public void registerBouncyCastleProvider(List<String> cipherTransformations, ShutdownContext shutdownContext) {
Provider provider = Security.getProvider(SecurityProviderUtils.BOUNCYCASTLE_PROVIDER_NAME);
if (provider == null) {
provider = Security.getProvider(SecurityProviderUtils.BOUNCYCASTLE_FIPS_PROVIDER_NAME);
}
if (provider == null) {
// TODO: Fix BuildStep execution order so that this is not required
// https://github.com/apache/camel-quarkus/issues/3472
provider = new BouncyCastleProvider();
Security.addProvider(provider);
try {
provider = (Provider) Thread.currentThread().getContextClassLoader()
.loadClass(SecurityProviderUtils.BOUNCYCASTLE_PROVIDER_CLASS_NAME).getConstructor().newInstance();
Security.addProvider(provider);
} catch (ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException
| NoSuchMethodException e) {
try {
//try to load BCFIPS
provider = (Provider) Thread.currentThread().getContextClassLoader()
.loadClass(SecurityProviderUtils.BOUNCYCASTLE_FIPS_PROVIDER_CLASS_NAME).getConstructor()
.newInstance();
Security.addProvider(provider);
} catch (ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException
| NoSuchMethodException e2) {
throw new RuntimeException("Neither BC nor BCFIPS provider can be registered. \nBC: " + e.getMessage()
+ "\nBCFIPS " + e2.getMessage());
}
}
}

// Make it explicit to the static analysis that below security services should be registered as they are reachable at runtime
Expand Down
67 changes: 67 additions & 0 deletions extensions/crypto-pgp/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-crypto-pgp-parent</artifactId>
<version>3.14.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>camel-quarkus-crypto-pgp-deployment</artifactId>
<name>Camel Quarkus :: PGP :: Deployment</name>

<dependencies>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-crypto-pgp</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-support-bouncycastle-deployment</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

</project>
Loading

0 comments on commit ed8156c

Please sign in to comment.