Skip to content

Commit 705b4cc

Browse files
committed
Add Client Certificate Mapper framework for mTLS support
- Implement complete Client Certificate Mapper framework - Add isEnabled() method to respect configuration - Default to enabled for mTLS client certificate authentication - Register framework in both supply and finalize phases - Add manifest entry with SHA256 hash verification - Include 2 integration tests (both passing) The framework maps Cloud Foundry X-Forwarded-Client-Cert headers to javax.servlet.request.X509Certificate for Java applications. Users can disable with: JBP_CONFIG_CLIENT_CERTIFICATE_MAPPER='{enabled: false}'
1 parent a52569a commit 705b4cc

5 files changed

Lines changed: 152 additions & 0 deletions

File tree

manifest.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ default_versions:
3636
version: 2.x
3737
- name: java-cfenv
3838
version: 3.x
39+
- name: client-certificate-mapper
40+
version: 2.x
3941
- name: postgresql-jdbc
4042
version: 42.x
4143
- name: mariadb-jdbc
@@ -106,6 +108,9 @@ url_to_dependency_map:
106108
- match: java-cfenv-(\d+\.\d+\.\d+)
107109
name: java-cfenv
108110
version: $1
111+
- match: client-certificate-mapper-(\d+\.\d+\.\d+)
112+
name: client-certificate-mapper
113+
version: $1
109114
- match: postgresql-(\d+\.\d+\.\d+)
110115
name: postgresql-jdbc
111116
version: $1
@@ -471,6 +476,15 @@ dependencies:
471476
- cflinuxfs4
472477
- cflinuxfs3
473478

479+
# Client Certificate Mapper (mTLS support)
480+
- name: client-certificate-mapper
481+
version: 2.0.1
482+
uri: https://java-buildpack.cloudfoundry.org/client-certificate-mapper/client-certificate-mapper-2.0.1.jar
483+
sha256: f7f53a460bcd4b0cead4da99dcb251bd283bd5fa4e421eeb52b86986d266cde9
484+
cf_stacks:
485+
- cflinuxfs4
486+
- cflinuxfs3
487+
474488
# PostgreSQL JDBC Driver
475489
- name: postgresql-jdbc
476490
version: 42.7.4

src/integration/frameworks_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,38 @@ func testFrameworks(platform switchblade.Platform, fixtures string) func(*testin
517517
})
518518
})
519519

520+
context("mTLS Support", func() {
521+
context("with Client Certificate Mapper enabled", func() {
522+
it("detects and installs Client Certificate Mapper for mTLS support", func() {
523+
deployment, logs, err := platform.Deploy.
524+
WithEnv(map[string]string{
525+
"BP_JAVA_VERSION": "11",
526+
"JBP_CONFIG_CLIENT_CERTIFICATE_MAPPER": "'{enabled: true}'",
527+
}).
528+
Execute(name, filepath.Join(fixtures, "container_tomcat"))
529+
Expect(err).NotTo(HaveOccurred(), logs.String)
530+
531+
// Client Certificate Mapper should be detected and installed
532+
Expect(logs.String()).To(ContainSubstring("Client Certificate Mapper"))
533+
Expect(deployment.ExternalURL).NotTo(BeEmpty())
534+
})
535+
536+
it("skips Client Certificate Mapper when disabled", func() {
537+
deployment, logs, err := platform.Deploy.
538+
WithEnv(map[string]string{
539+
"BP_JAVA_VERSION": "11",
540+
"JBP_CONFIG_CLIENT_CERTIFICATE_MAPPER": "'{enabled: false}'",
541+
}).
542+
Execute(name, filepath.Join(fixtures, "container_tomcat"))
543+
Expect(err).NotTo(HaveOccurred(), logs.String)
544+
545+
// Should not install when explicitly disabled
546+
Expect(logs.String()).NotTo(ContainSubstring("Client Certificate Mapper"))
547+
Expect(deployment.ExternalURL).NotTo(BeEmpty())
548+
})
549+
})
550+
})
551+
520552
context("Utility Frameworks", func() {
521553
context("with Debug enabled", func() {
522554
it("configures remote debugging via JDWP", func() {

src/java/finalize/finalize.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ func (f *Finalizer) finalizeFrameworks() error {
162162
registry.Register(frameworks.NewPostgresqlJdbcFramework(ctx))
163163
registry.Register(frameworks.NewMariaDBJDBCFramework(ctx))
164164

165+
// mTLS Support (Priority 1)
166+
registry.Register(frameworks.NewClientCertificateMapperFramework(ctx))
167+
165168
// Development Tools (Priority 1)
166169
registry.Register(frameworks.NewDebugFramework(ctx))
167170
registry.Register(frameworks.NewJmxFramework(ctx))
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package frameworks
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
)
8+
9+
// ClientCertificateMapperFramework implements mTLS client certificate mapper support
10+
// This framework provides automatic mapping of Cloud Foundry client certificates
11+
// for mutual TLS (mTLS) authentication in Java applications
12+
type ClientCertificateMapperFramework struct {
13+
context *Context
14+
}
15+
16+
// NewClientCertificateMapperFramework creates a new client certificate mapper framework instance
17+
func NewClientCertificateMapperFramework(ctx *Context) *ClientCertificateMapperFramework {
18+
return &ClientCertificateMapperFramework{context: ctx}
19+
}
20+
21+
// Detect checks if client certificate mapper should be included
22+
// Enabled by default to support mTLS scenarios, can be disabled via configuration
23+
func (c *ClientCertificateMapperFramework) Detect() (string, error) {
24+
// Check if explicitly disabled via configuration
25+
if !c.isEnabled() {
26+
return "", nil
27+
}
28+
29+
// Enabled by default to support mTLS client certificate authentication
30+
return "Client Certificate Mapper", nil
31+
}
32+
33+
// Supply installs the client certificate mapper JAR
34+
func (c *ClientCertificateMapperFramework) Supply() error {
35+
c.context.Log.BeginStep("Installing Client Certificate Mapper")
36+
37+
// Get client-certificate-mapper dependency from manifest
38+
dep, err := c.context.Manifest.DefaultVersion("client-certificate-mapper")
39+
if err != nil {
40+
return fmt.Errorf("unable to determine Client Certificate Mapper version: %w", err)
41+
}
42+
43+
// Install client certificate mapper JAR
44+
mapperDir := filepath.Join(c.context.Stager.DepDir(), "client_certificate_mapper")
45+
if err := c.context.Installer.InstallDependency(dep, mapperDir); err != nil {
46+
return fmt.Errorf("failed to install Client Certificate Mapper: %w", err)
47+
}
48+
49+
c.context.Log.Info("Installed Client Certificate Mapper version %s", dep.Version)
50+
return nil
51+
}
52+
53+
// Finalize adds the client certificate mapper JAR to the application classpath
54+
func (c *ClientCertificateMapperFramework) Finalize() error {
55+
// Find the installed JAR
56+
mapperDir := filepath.Join(c.context.Stager.DepDir(), "client_certificate_mapper")
57+
jarPattern := filepath.Join(mapperDir, "client-certificate-mapper-*.jar")
58+
59+
matches, err := filepath.Glob(jarPattern)
60+
if err != nil || len(matches) == 0 {
61+
// JAR not found, might not have been installed
62+
return nil
63+
}
64+
65+
// Add to classpath via CLASSPATH environment variable
66+
classpath := os.Getenv("CLASSPATH")
67+
if classpath != "" {
68+
classpath += ":"
69+
}
70+
classpath += matches[0]
71+
72+
if err := c.context.Stager.WriteEnvFile("CLASSPATH", classpath); err != nil {
73+
return fmt.Errorf("failed to set CLASSPATH for Client Certificate Mapper: %w", err)
74+
}
75+
76+
return nil
77+
}
78+
79+
// isEnabled checks if client certificate mapper is enabled
80+
// Default is true (enabled) to support mTLS scenarios unless explicitly disabled
81+
func (c *ClientCertificateMapperFramework) isEnabled() bool {
82+
// Check JBP_CONFIG_CLIENT_CERTIFICATE_MAPPER environment variable
83+
config := os.Getenv("JBP_CONFIG_CLIENT_CERTIFICATE_MAPPER")
84+
85+
// Parse the config to check for enabled: false
86+
// For simplicity, if JBP_CONFIG_CLIENT_CERTIFICATE_MAPPER is set and contains "enabled", check its value
87+
// A more robust implementation would parse YAML
88+
if config != "" {
89+
// Simple check: if it contains "enabled: false" or "'enabled': false"
90+
if contains(config, "enabled: false") || contains(config, "'enabled': false") {
91+
return false
92+
}
93+
if contains(config, "enabled: true") || contains(config, "'enabled': true") {
94+
return true
95+
}
96+
}
97+
98+
// Default to enabled (to support mTLS client certificate authentication)
99+
return true
100+
}

src/java/supply/supply.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ func (s *Supplier) installFrameworks() error {
167167
registry.Register(frameworks.NewPostgresqlJdbcFramework(ctx))
168168
registry.Register(frameworks.NewMariaDBJDBCFramework(ctx))
169169

170+
// mTLS Support (Priority 1)
171+
registry.Register(frameworks.NewClientCertificateMapperFramework(ctx))
172+
170173
// Development Tools (Priority 1)
171174
registry.Register(frameworks.NewDebugFramework(ctx))
172175
registry.Register(frameworks.NewJmxFramework(ctx))

0 commit comments

Comments
 (0)