This is an automated email from the ASF dual-hosted git repository.
hanicz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new 9c000de37 KNOX-3316: Change downloaded keystore format based on FIPS
(#1292)
9c000de37 is described below
commit 9c000de3747fd9db626b6a930ac0fac6450cab05
Author: hanicz <[email protected]>
AuthorDate: Thu Jul 2 10:56:31 2026 +0200
KNOX-3316: Change downloaded keystore format based on FIPS (#1292)
---
.../service/metadata/GeneralProxyInformation.java | 66 ++++++++++++++
.../service/metadata/KnoxMetadataResource.java | 100 +++++++++++++--------
.../general.proxy.information.component.html | 2 +-
.../general.proxy.information.component.ts | 7 ++
.../home/app/model/general.proxy.information.ts | 1 +
5 files changed, 138 insertions(+), 38 deletions(-)
diff --git
a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformation.java
b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformation.java
index 833f0d341..d15603a69 100644
---
a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformation.java
+++
b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/GeneralProxyInformation.java
@@ -55,6 +55,10 @@ public class GeneralProxyInformation {
@ApiModelProperty(value = "A boolean flag indicating whether Webshell UI
should be enabled on the Knox Home page")
private String enableWebshell = "false";
+ @XmlElement
+ @ApiModelProperty(value = "The truststore type the homepage should offer for
download (e.g. 'jks' or 'bcfks')")
+ private String truststoreType = "jks";
+
public String getVersion() {
return version;
}
@@ -112,4 +116,66 @@ public class GeneralProxyInformation {
this.enableWebshell = enableWebshell;
}
+ public String getTruststoreType() {
+ return truststoreType;
+ }
+
+ public void setTruststoreType(String truststoreType) {
+ this.truststoreType = truststoreType;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private final GeneralProxyInformation instance = new
GeneralProxyInformation();
+
+ private Builder() {}
+
+ public Builder version(String version) {
+ instance.setVersion(version);
+ return this;
+ }
+
+ public Builder hostname(String hostname) {
+ instance.setHostname(hostname);
+ return this;
+ }
+
+ public Builder adminUiUrl(String adminUiUrl) {
+ instance.setAdminUiUrl(adminUiUrl);
+ return this;
+ }
+
+ public Builder webShellUrl(String webShellUrl) {
+ instance.setWebShellUrl(webShellUrl);
+ return this;
+ }
+
+ public Builder adminApiBookUrl(String adminApiBookUrl) {
+ instance.setAdminApiBookUrl(adminApiBookUrl);
+ return this;
+ }
+
+ public Builder enableTokenManagement(boolean enableTokenManagement) {
+
instance.setEnableTokenManagement(Boolean.toString(enableTokenManagement));
+ return this;
+ }
+
+ public Builder enableWebshell(boolean enableWebshell) {
+ instance.setEnableWebshell(Boolean.toString(enableWebshell));
+ return this;
+ }
+
+ public Builder truststoreType(String truststoreType) {
+ instance.setTruststoreType(truststoreType);
+ return this;
+ }
+
+ public GeneralProxyInformation build() {
+ return instance;
+ }
+ }
+
}
diff --git
a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataResource.java
b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataResource.java
index ba77c0e5d..23e61a9f3 100644
---
a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataResource.java
+++
b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/KnoxMetadataResource.java
@@ -54,6 +54,7 @@ import javax.ws.rs.core.Response.Status;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.dto.HomePageProfile;
+import org.apache.knox.gateway.fips.FipsUtils;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
import org.apache.knox.gateway.service.definition.Metadata;
import org.apache.knox.gateway.service.definition.ServiceDefinitionPair;
@@ -98,39 +99,49 @@ public class KnoxMetadataResource {
@Produces({ APPLICATION_JSON, APPLICATION_XML })
@Path("info")
public GeneralProxyInformation getGeneralProxyInformation() {
- final GeneralProxyInformation proxyInfo = new GeneralProxyInformation();
final GatewayServices gatewayServices = (GatewayServices)
request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
- if (gatewayServices != null) {
- final ServerInfoService serviceInfoService =
gatewayServices.getService(ServiceType.SERVER_INFO_SERVICE);
- final String versionInfo = serviceInfoService.getBuildVersion() + "
(hash=" + serviceInfoService.getBuildHash() + ")";
- proxyInfo.setVersion(versionInfo);
- proxyInfo.setHostname(Hostname.getHostname());
- proxyInfo.setAdminApiBookUrl(
- String.format(Locale.ROOT,
"https://knox.apache.org/books/knox-%s/user-guide.html#Admin+API",
getAdminApiBookVersion(serviceInfoService.getBuildVersion())));
- final GatewayConfig config = (GatewayConfig)
request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
- proxyInfo.setAdminUiUrl(getBaseGatewayUrl(config) +
"/manager/admin-ui/");
- proxyInfo.setWebShellUrl(getBaseGatewayUrl(config) +
"/homepage/webshell-ui/index.html");
- setTokenManagementEnabledFlag(proxyInfo, gatewayServices);
- proxyInfo.setEnableWebshell(String.valueOf(config.isWebShellEnabled()));
+ if (gatewayServices == null) {
+ return GeneralProxyInformation.builder().build();
}
+ final GatewayConfig config = (GatewayConfig)
request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+ final ServerInfoService serverInfo =
gatewayServices.getService(ServiceType.SERVER_INFO_SERVICE);
+ final String baseGatewayUrl = getBaseGatewayUrl(config);
- return proxyInfo;
+ return GeneralProxyInformation.builder()
+ .version(serverInfo.getBuildVersion() + " (hash=" +
serverInfo.getBuildHash() + ")")
+ .hostname(Hostname.getHostname())
+ .adminUiUrl(baseGatewayUrl + "/manager/admin-ui/")
+ .webShellUrl(baseGatewayUrl + "/homepage/webshell-ui/index.html")
+ .adminApiBookUrl(buildAdminApiBookUrl(serverInfo.getBuildVersion()))
+ .enableTokenManagement(isTokenManagementEnabled(gatewayServices))
+ .enableWebshell(config.isWebShellEnabled())
+ .truststoreType(preferredTruststoreType())
+ .build();
}
- private void setTokenManagementEnabledFlag(final GeneralProxyInformation
proxyInfo, final GatewayServices gatewayServices) {
+ private boolean isTokenManagementEnabled(final GatewayServices
gatewayServices) {
try {
final AliasService aliasService =
gatewayServices.getService(ServiceType.ALIAS_SERVICE);
final List<String> aliases =
aliasService.getAliasesForCluster(AliasService.NO_CLUSTER_NAME);
final boolean tokenManagementEnabled =
aliases.contains(TokenMAC.KNOX_TOKEN_HASH_KEY_ALIAS_NAME);
-
proxyInfo.setEnableTokenManagement(Boolean.toString(tokenManagementEnabled));
if (!tokenManagementEnabled) {
LOG.tokenManagementDisabled();
}
+ return tokenManagementEnabled;
} catch (AliasServiceException e) {
LOG.failedToFetchGatewayAliasList(e.getMessage(), e);
+ return false;
}
}
+ private String buildAdminApiBookUrl(String buildVersion) {
+ return String.format(Locale.ROOT,
"https://knox.apache.org/books/knox-%s/user-guide.html#Admin+API",
getAdminApiBookVersion(buildVersion));
+ }
+
+ private String preferredTruststoreType() {
+ return FipsUtils.isFipsEnabledWithBCProvider() ? "bcfks" : "jks";
+ }
+
private String getAdminApiBookVersion(String buildVersion) {
return buildVersion.replaceAll(SNAPSHOT_VERSION_POSTFIX,
"").replaceAll("\\.", "-");
}
@@ -142,18 +153,21 @@ public class KnoxMetadataResource {
final GatewayConfig config = (GatewayConfig)
request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
final Certificate[] certificateChain = config.isSSLEnabled() ?
getPublicCertificates() : getSigningkeyCerts(config);
if (certificateChain != null) {
+ final java.nio.file.Path certFilePath;
if ("pem".equals(certType)) {
- generateCertificatePem(certificateChain, config);
- return generateSuccessFileDownloadResponse(pemFilePath);
+ certFilePath = generateCertificatePem(certificateChain, config);
} else if ("jks".equals(certType)) {
- generateCertificateJks(certificateChain, config);
- return generateSuccessFileDownloadResponse(jksFilePath);
+ certFilePath = generateCertificateJks(certificateChain, config);
} else if ("bcfks".equals(certType)) {
- generateCertificateBcfks(certificateChain, config);
- return generateSuccessFileDownloadResponse(bcfksFilePath);
+ certFilePath = generateCertificateBcfks(certificateChain, config);
} else {
return generateFailureFileDownloadResponse(Status.BAD_REQUEST,
"Invalid certification type provided!");
}
+ if (certFilePath != null && certFilePath.toFile().exists()) {
+ return generateSuccessFileDownloadResponse(certFilePath);
+ }
+ return generateFailureFileDownloadResponse(Status.SERVICE_UNAVAILABLE,
+ "Could not generate " + certType.toUpperCase(Locale.ROOT) + " public
certificate");
}
return generateFailureFileDownloadResponse(Status.SERVICE_UNAVAILABLE,
"Could not generate public certificate");
}
@@ -190,36 +204,48 @@ public class KnoxMetadataResource {
return null;
}
- private void generateCertificatePem(Certificate[] certificateChain,
GatewayConfig gatewayConfig) {
+ private java.nio.file.Path generateCertificatePem(Certificate[]
certificateChain, GatewayConfig gatewayConfig) {
+ if (pemFilePath != null && pemFilePath.toFile().exists()) {
+ return pemFilePath;
+ }
+ final java.nio.file.Path candidate =
Paths.get(gatewayConfig.getGatewaySecurityDir(), "gateway-client-trust.pem");
try {
- if (pemFilePath == null || !pemFilePath.toFile().exists()) {
- pemFilePath = Paths.get(gatewayConfig.getGatewaySecurityDir(),
"gateway-client-trust.pem");
- X509CertificateUtil.writeCertificatesToFile(certificateChain,
pemFilePath.toFile());
- }
+ X509CertificateUtil.writeCertificatesToFile(certificateChain,
candidate.toFile());
+ pemFilePath = candidate;
+ return pemFilePath;
} catch (CertificateEncodingException | IOException e) {
LOG.failedToGeneratePublicCert("PEM", e.getMessage(), e);
+ return null;
}
}
- private void generateCertificateJks(Certificate[] certificateChain,
GatewayConfig gatewayConfig) {
+ private java.nio.file.Path generateCertificateJks(Certificate[]
certificateChain, GatewayConfig gatewayConfig) {
+ if (jksFilePath != null && jksFilePath.toFile().exists()) {
+ return jksFilePath;
+ }
+ final java.nio.file.Path candidate =
Paths.get(gatewayConfig.getGatewaySecurityDir(), "gateway-client-trust.jks");
try {
- if (jksFilePath == null || !jksFilePath.toFile().exists()) {
- jksFilePath = Paths.get(gatewayConfig.getGatewaySecurityDir(),
"gateway-client-trust.jks");
- X509CertificateUtil.writeCertificatesToJks(certificateChain,
jksFilePath.toFile(), null);
- }
+ X509CertificateUtil.writeCertificatesToJks(certificateChain,
candidate.toFile(), null);
+ jksFilePath = candidate;
+ return jksFilePath;
} catch (IOException | KeyStoreException | NoSuchAlgorithmException |
CertificateException e) {
LOG.failedToGeneratePublicCert("JKS", e.getMessage(), e);
+ return null;
}
}
- private void generateCertificateBcfks(Certificate[] certificateChain,
GatewayConfig gatewayConfig) {
+ private java.nio.file.Path generateCertificateBcfks(Certificate[]
certificateChain, GatewayConfig gatewayConfig) {
+ if (bcfksFilePath != null && bcfksFilePath.toFile().exists()) {
+ return bcfksFilePath;
+ }
+ final java.nio.file.Path candidate =
Paths.get(gatewayConfig.getGatewaySecurityDir(), "gateway-client-trust.bcfks");
try {
- if (bcfksFilePath == null || !bcfksFilePath.toFile().exists()) {
- bcfksFilePath = Paths.get(gatewayConfig.getGatewaySecurityDir(),
"gateway-client-trust.bcfks");
- X509CertificateUtil.writeCertificatesToBcfks(certificateChain,
bcfksFilePath.toFile(), null);
- }
+ X509CertificateUtil.writeCertificatesToBcfks(certificateChain,
candidate.toFile(), null);
+ bcfksFilePath = candidate;
+ return bcfksFilePath;
} catch (IOException | KeyStoreException | NoSuchAlgorithmException |
CertificateException e) {
LOG.failedToGeneratePublicCert("BCFKS", e.getMessage(), e);
+ return null;
}
}
diff --git
a/knox-homepage-ui/home/app/generalProxyInformation/general.proxy.information.component.html
b/knox-homepage-ui/home/app/generalProxyInformation/general.proxy.information.component.html
index fb3b097ce..1cef2a53c 100644
---
a/knox-homepage-ui/home/app/generalProxyInformation/general.proxy.information.component.html
+++
b/knox-homepage-ui/home/app/generalProxyInformation/general.proxy.information.component.html
@@ -49,7 +49,7 @@ limitations under the License.
<td>
<a href="{{ getMetadataAPIUrl('publicCert?type=pem') }}">PEM</a>
|
- <a href="{{ getMetadataAPIUrl('publicCert?type=jks') }}">JKS</a>
+ <a href="{{ getMetadataAPIUrl('publicCert?type=' +
getTruststoreType()) }}">{{ getTruststoreType().toUpperCase() }}</a>
</td>
</tr>
}
diff --git
a/knox-homepage-ui/home/app/generalProxyInformation/general.proxy.information.component.ts
b/knox-homepage-ui/home/app/generalProxyInformation/general.proxy.information.component.ts
index 9bba05fc0..d2d7ce5c0 100644
---
a/knox-homepage-ui/home/app/generalProxyInformation/general.proxy.information.component.ts
+++
b/knox-homepage-ui/home/app/generalProxyInformation/general.proxy.information.component.ts
@@ -111,6 +111,13 @@ export class GeneralProxyInformationComponent implements
OnInit {
return false;
}
+ getTruststoreType() {
+ if (this.generalProxyInformation &&
this.generalProxyInformation.truststoreType) {
+ return this.generalProxyInformation.truststoreType;
+ }
+ return 'jks';
+ }
+
ngOnInit(): void {
console.debug('GeneralProxyInformationComponent --> ngOnInit() --> ');
this.homepageService.getGeneralProxyInformation()
diff --git a/knox-homepage-ui/home/app/model/general.proxy.information.ts
b/knox-homepage-ui/home/app/model/general.proxy.information.ts
index 3efe82389..0a3184891 100644
--- a/knox-homepage-ui/home/app/model/general.proxy.information.ts
+++ b/knox-homepage-ui/home/app/model/general.proxy.information.ts
@@ -23,4 +23,5 @@ export class GeneralProxyInformation {
adminApiBookUrl: string;
enableTokenManagement: string;
enableWebshell: string;
+ truststoreType: string;
}