multiple client CAs
This commit is contained in:
@@ -20,7 +20,8 @@ tls:
|
||||
key: "server.p8.key"
|
||||
client:
|
||||
require: true
|
||||
ca: "ca.crt"
|
||||
cas:
|
||||
- "ca.crt"
|
||||
|
||||
compression:
|
||||
grpc:
|
||||
@@ -40,7 +41,7 @@ It configures following:
|
||||
- compression is disabled for gRPC-server (enabled by default)
|
||||
- compression is disabled for upstream gRPC-client (enabled by default)
|
||||
- server certificate is located at `server.crt` with the key for it at `server.p8.key`
|
||||
- the server requires a client authentication by TLS client certificate signed by `ca.crt` certificate
|
||||
- the server requires a client authentication by TLS client certificate signed by `ca.crt` certificate.
|
||||
- no JSON RPC is configured
|
||||
- upstreams configuration is configured in the file `upstreams.yaml`
|
||||
|
||||
|
||||
@@ -180,15 +180,17 @@ tls:
|
||||
----
|
||||
| Path to certificate and certificate private key
|
||||
|
||||
a| `client.ca`, `client.required`
|
||||
a| `client.ca`, `client.cas`, `client.required`
|
||||
a|
|
||||
[source,yaml]
|
||||
----
|
||||
tls:
|
||||
client:
|
||||
ca: ca.crt
|
||||
cas:
|
||||
- ca1.crt
|
||||
- ca2.crt
|
||||
required: true
|
||||
----
|
||||
a| Path to CA used to authenticate incoming connections, used if `required: true`
|
||||
a| Paths to CA used to authenticate incoming connections, used if `required: true`
|
||||
|
||||
|===
|
||||
@@ -26,6 +26,7 @@ import org.apache.commons.lang3.StringUtils
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.stereotype.Service
|
||||
import java.security.cert.CertificateFactory
|
||||
|
||||
@Service
|
||||
open class TlsSetup(
|
||||
@@ -77,10 +78,18 @@ open class TlsSetup(
|
||||
fileResolver.resolve(config.key!!)
|
||||
)
|
||||
}
|
||||
if (StringUtils.isNotEmpty(config.clientCa)) {
|
||||
if (config.clientCAs.isNotEmpty()) {
|
||||
log.info("Using TLS for client authentication for $category")
|
||||
val cf = CertificateFactory.getInstance("X.509")
|
||||
sslContextBuilder.trustManager(
|
||||
fileResolver.resolve(config.clientCa!!)
|
||||
|
||||
config.clientCAs
|
||||
.map { fileResolver.resolve(it) }
|
||||
.map { file ->
|
||||
file.inputStream().use {
|
||||
cf.generateCertificate(it) as java.security.cert.X509Certificate
|
||||
}
|
||||
}
|
||||
)
|
||||
if (config.clientRequire != null && config.clientRequire!!) {
|
||||
sslContextBuilder.clientAuth(ClientAuth.REQUIRE)
|
||||
|
||||
@@ -56,6 +56,6 @@ class AuthConfig {
|
||||
var certificate: String? = null
|
||||
var key: String? = null
|
||||
var clientRequire: Boolean? = null
|
||||
var clientCa: String? = null
|
||||
var clientCAs: MutableList<String> = mutableListOf()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.config
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.yaml.snakeyaml.nodes.MappingNode
|
||||
import org.yaml.snakeyaml.nodes.ScalarNode
|
||||
|
||||
class AuthConfigReader : YamlConfigReader<AuthConfig>() {
|
||||
|
||||
@@ -77,7 +78,15 @@ class AuthConfigReader : YamlConfigReader<AuthConfig>() {
|
||||
getValueAsBool(clientNode, "require")?.let {
|
||||
auth.clientRequire = it
|
||||
}
|
||||
auth.clientCa = getValueAsString(clientNode, "ca")
|
||||
getValueAsString(clientNode, "ca")?.let {
|
||||
auth.clientCAs.add(it)
|
||||
}
|
||||
getList<ScalarNode>(clientNode, "cas")?.let {
|
||||
println(it)
|
||||
it.value?.let { crt ->
|
||||
auth.clientCAs.addAll(crt.map { v -> v.value })
|
||||
}
|
||||
}
|
||||
}
|
||||
auth
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class TlsSetupSpec extends Specification {
|
||||
certificate: "127.0.0.1.crt",
|
||||
key: "127.0.0.1.p8.key",
|
||||
clientRequire: true,
|
||||
clientCa: "ca.myhost.dev.crt"
|
||||
clientCAs: ["ca.myhost.dev.crt"]
|
||||
)
|
||||
when:
|
||||
def act = tlsSetup.setupServer("test", config, false)
|
||||
@@ -182,12 +182,12 @@ class TlsSetupSpec extends Specification {
|
||||
certificate: "127.0.0.1.crt",
|
||||
key: "127.0.0.1.p8.key",
|
||||
clientRequire: true,
|
||||
clientCa: "none.crt"
|
||||
clientCAs: ["none.crt"]
|
||||
)
|
||||
when:
|
||||
tlsSetup.setupServer("test", config, false)
|
||||
then:
|
||||
def t = thrown(IllegalArgumentException)
|
||||
def t = thrown(FileNotFoundException)
|
||||
}
|
||||
|
||||
def "Fail if client certificate is invalid"() {
|
||||
@@ -197,11 +197,11 @@ class TlsSetupSpec extends Specification {
|
||||
certificate: "127.0.0.1.crt",
|
||||
key: "127.0.0.1.p8.key",
|
||||
clientRequire: true,
|
||||
clientCa: "ca.myhost.dev.key"
|
||||
clientCAs: ["ca.myhost.dev.key"]
|
||||
)
|
||||
when:
|
||||
tlsSetup.setupServer("test", config, false)
|
||||
then:
|
||||
def t = thrown(IllegalArgumentException)
|
||||
def t = thrown(java.security.cert.CertificateParsingException)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,6 @@ class AuthConfigReaderSpec extends Specification {
|
||||
act.key == "/etc/client1.myservice.com.key"
|
||||
act.clientRequire != null
|
||||
!act.clientRequire
|
||||
act.clientCa == "/etc/ca.myservice.com.crt"
|
||||
act.clientCAs == ["/etc/ca.myservice.com.crt"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class MainConfigReaderSpec extends Specification {
|
||||
certificate == "/path/127.0.0.1.crt"
|
||||
key == "/path/127.0.0.1.p8.key"
|
||||
!clientRequire
|
||||
clientCa == "/path/ca.dshackle.test.crt"
|
||||
clientCAs == ["/path/ca.dshackle.test.crt"]
|
||||
}
|
||||
act.cache != null
|
||||
with(act.cache) {
|
||||
|
||||
Reference in New Issue
Block a user