Skip to content

Commit

Permalink
Support for configuring SunPKCS11 providers
Browse files Browse the repository at this point in the history
  • Loading branch information
sberyozkin committed Apr 22, 2022
1 parent 6d85f44 commit 187d8e0
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 9 deletions.
34 changes: 34 additions & 0 deletions docs/src/main/asciidoc/security-customization.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,40 @@ keytool -genkey -alias server -keyalg RSA -keystore server-keystore.jks -keysize
`BCFIPSJSSE` provider option is currently not supported in native image.
====

[[sun-pkcs11]]
=== SunPKCS11

`SunPKCS11` provider provides a bridge to specific `PKCS#11` implementations such as cryptographic smartcards and other Hardware Security Modules, Network Security Services in FIPS mode, etc.

Typically, in order to work with `SunPKCS11`, one needs to install a `PKCS#11` implementation, generate a configuration which usually refers to a shared library, token slot, etc and write the following Java code:

[source,java]
----
import java.security.Provider;
import java.security.Security;
String configuration = "pkcs11.cfg"
Provider sunPkcs11 = Security.getProvider("SunPKCS11");
Provider pkcsImplementation = sunPkcs11.configure(configuration);
// or prepare configuration in the code or read it from the file such as "pkcs11.cfg" and do
// sunPkcs11.configure("--" + configuration);
Security.addProvider(pkcsImplementation);
----

In Quarkus you can achieve the same at the configuration level only without having to modify the code, for example:

[source,properties]
----
quarkus.security.security-providers=SunPKCS11
quarkus.security.security-provider-config.SunPKCS11=pkcs11.cfg
----

[NOTE]
====
Note that while accessing the `SunPKCS11` bridge provider is supported in native image, configuring `SunPKCS11` is currently not supported in native image at the Quarkus level.
====

== Reactive Security

If you are going to use security in a reactive environment, you will likely need SmallRye Context Propagation:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@
* Metadata for the names of JCA {@linkplain java.security.Provider} to register for reflection
*/
public final class JCAProviderBuildItem extends MultiBuildItem {
private String providerName;
final private String providerName;
final private String providerConfig;

public JCAProviderBuildItem(String providerName) {
public JCAProviderBuildItem(String providerName, String providerConfig) {
this.providerName = providerName;
this.providerConfig = providerConfig;
}

public String getProviderName() {
return providerName;
}

public String getProviderConfig() {
return providerConfig;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package io.quarkus.security.deployment;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
Expand All @@ -20,8 +21,14 @@ public final class SecurityConfig {
public boolean authorizationEnabledInDevMode;

/**
* List of security providers to enable for reflection
* List of security providers to register
*/
@ConfigItem
public Optional<List<String>> securityProviders;
public Optional<Set<String>> securityProviders;

/**
* Security provider configuration
*/
@ConfigItem
public Map<String, String> securityProviderConfig;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -94,7 +93,7 @@ public class SecurityProcessor {
void produceJcaSecurityProviders(BuildProducer<JCAProviderBuildItem> jcaProviders,
BuildProducer<BouncyCastleProviderBuildItem> bouncyCastleProvider,
BuildProducer<BouncyCastleJsseProviderBuildItem> bouncyCastleJsseProvider) {
Set<String> providers = new HashSet<>(security.securityProviders.orElse(Collections.emptyList()));
Set<String> providers = security.securityProviders.orElse(Set.of());
for (String providerName : providers) {
if (SecurityProviderUtils.BOUNCYCASTLE_PROVIDER_NAME.equals(providerName)) {
bouncyCastleProvider.produce(new BouncyCastleProviderBuildItem());
Expand All @@ -105,7 +104,7 @@ void produceJcaSecurityProviders(BuildProducer<JCAProviderBuildItem> jcaProvider
} else if (SecurityProviderUtils.BOUNCYCASTLE_FIPS_JSSE_PROVIDER_NAME.equals(providerName)) {
bouncyCastleJsseProvider.produce(new BouncyCastleJsseProviderBuildItem(true));
} else {
jcaProviders.produce(new JCAProviderBuildItem(providerName));
jcaProviders.produce(new JCAProviderBuildItem(providerName, security.securityProviderConfig.get(providerName)));
}
log.debugf("Added providerName: %s", providerName);
}
Expand All @@ -124,7 +123,8 @@ void registerJCAProvidersForReflection(BuildProducer<ReflectiveClassBuildItem> c
List<JCAProviderBuildItem> jcaProviders,
BuildProducer<NativeImageSecurityProviderBuildItem> additionalProviders) throws IOException, URISyntaxException {
for (JCAProviderBuildItem provider : jcaProviders) {
List<String> providerClasses = registerProvider(provider.getProviderName(), additionalProviders);
List<String> providerClasses = registerProvider(provider.getProviderName(), provider.getProviderConfig(),
additionalProviders);
for (String className : providerClasses) {
classes.produce(new ReflectiveClassBuildItem(true, true, className));
log.debugf("Register JCA class: %s", className);
Expand Down Expand Up @@ -354,6 +354,7 @@ private <BI extends MultiBuildItem> Optional<BI> getOne(List<BI> items) {
* @return class names that make up the provider and its services
*/
private List<String> registerProvider(String providerName,
String providerConfig,
BuildProducer<NativeImageSecurityProviderBuildItem> additionalProviders) {
List<String> providerClasses = new ArrayList<>();
Provider provider = Security.getProvider(providerName);
Expand All @@ -367,6 +368,14 @@ private List<String> registerProvider(String providerName,
providerClasses.addAll(Arrays.asList(supportedKeyClasses.split("\\|")));
}
}

if (providerConfig != null) {
Provider configuredProvider = provider.configure(providerConfig);
if (configuredProvider != null) {
Security.addProvider(configuredProvider);
providerClasses.add(configuredProvider.getClass().getName());
}
}
}

if (SecurityProviderUtils.SUN_PROVIDERS.containsKey(providerName)) {
Expand Down

0 comments on commit 187d8e0

Please sign in to comment.