Implement mutual TLS authentication Add a pair of flags tls_client_certificate / tls_client_key to specify a certificate and corresponding key, which allow Bazel to authenticate itself over TLS to a remote cache or remote executor. Before this change, Bazel only supports Google Cloud authentication, which requires an open network connection to Google Cloud on the client as well as on the server. I have heard from one user that they are tunneling their traffic over a VPN and then perform no client authentication in their remote caching system. I heard from another user that they have locally patched Bazel to enable mTLS (but have not upstreamed the patch). Finally, there is also a pending feature request. Compared to other authentication mechanisms, mTLS is already supported by gRPC out of the box. I added test coverage by also adding a --tls_ca_certificate to the local remote worker, and updating the existing TLS test to also run with an mTLS configuration. I had to generate a new ca cert/key pair in order to sign a new client certificate (and also re-generate the server cert/key pair); these are checked in as testdata. Note that the generator script given there already supports generating both server and client cert/key pairs, so no change to the documentation was necessary. Fixes #10735. Change-Id: I8c9fdab11d172a4cc8a2b80de43faa48086cc893 Closes #11030. Change-Id: I8c9fdab11d172a4cc8a2b80de43faa48086cc893 NOKEYCHECK=True PiperOrigin-RevId: 304041337
diff --git a/src/main/java/com/google/devtools/build/lib/authandtls/AuthAndTLSOptions.java b/src/main/java/com/google/devtools/build/lib/authandtls/AuthAndTLSOptions.java index c5ab8a2..8dc077c 100644 --- a/src/main/java/com/google/devtools/build/lib/authandtls/AuthAndTLSOptions.java +++ b/src/main/java/com/google/devtools/build/lib/authandtls/AuthAndTLSOptions.java
@@ -86,15 +86,34 @@ public boolean incompatibleTlsEnabledRemoved; @Option( - name = "tls_certificate", - defaultValue = "null", - documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, - effectTags = {OptionEffectTag.UNKNOWN}, - help = "Specify the TLS client certificate to use." - ) + name = "tls_certificate", + defaultValue = "null", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.UNKNOWN}, + help = "Specify a path to a TLS certificate that is trusted to sign server certificates.") public String tlsCertificate; @Option( + name = "tls_client_certificate", + defaultValue = "null", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.UNKNOWN}, + help = + "Specify the TLS client certificate to use; you also need to provide a client key to " + + "enable client authentication.") + public String tlsClientCertificate; + + @Option( + name = "tls_client_key", + defaultValue = "null", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.UNKNOWN}, + help = + "Specify the TLS client key to use; you also need to provide a client certificate to " + + "enable client authentication.") + public String tlsClientKey; + + @Option( name = "tls_authority_override", defaultValue = "null", metadataTags = {OptionMetadataTag.HIDDEN},
diff --git a/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java b/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java index 52c81cd..1fc6cd9 100644 --- a/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java +++ b/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java
@@ -34,6 +34,7 @@ import io.netty.channel.kqueue.KQueueEventLoopGroup; import io.netty.channel.unix.DomainSocketAddress; import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -59,11 +60,13 @@ Preconditions.checkNotNull(target); Preconditions.checkNotNull(options); - final SslContext sslContext = - isTlsEnabled(target) ? createSSlContext(options.tlsCertificate) : null; + SslContext sslContext = + isTlsEnabled(target) + ? createSSlContext( + options.tlsCertificate, options.tlsClientCertificate, options.tlsClientKey) + : null; String targetUrl = convertTargetScheme(target); - try { NettyChannelBuilder builder = newNettyChannelBuilder(targetUrl, proxy) @@ -104,23 +107,40 @@ return !target.startsWith("grpc://"); } - private static SslContext createSSlContext(@Nullable String rootCert) throws IOException { - if (rootCert == null) { + private static SslContext createSSlContext( + @Nullable String rootCert, @Nullable String clientCert, @Nullable String clientKey) + throws IOException { + SslContextBuilder sslContextBuilder; + try { + sslContextBuilder = GrpcSslContexts.forClient(); + } catch (Exception e) { + String message = "Failed to init TLS infrastructure: " + e.getMessage(); + throw new IOException(message, e); + } + if (rootCert != null) { try { - return GrpcSslContexts.forClient().build(); - } catch (Exception e) { - String message = "Failed to init TLS infrastructure: " + e.getMessage(); - throw new IOException(message, e); - } - } else { - try { - return GrpcSslContexts.forClient().trustManager(new File(rootCert)).build(); + sslContextBuilder.trustManager(new File(rootCert)); } catch (Exception e) { String message = "Failed to init TLS infrastructure using '%s' as root certificate: %s"; message = String.format(message, rootCert, e.getMessage()); throw new IOException(message, e); } } + if (clientCert != null && clientKey != null) { + try { + sslContextBuilder.keyManager(new File(clientCert), new File(clientKey)); + } catch (Exception e) { + String message = "Failed to init TLS infrastructure using '%s' as client certificate: %s"; + message = String.format(message, clientCert, e.getMessage()); + throw new IOException(message, e); + } + } + try { + return sslContextBuilder.build(); + } catch (Exception e) { + String message = "Failed to init TLS infrastructure: " + e.getMessage(); + throw new IOException(message, e); + } } private static NettyChannelBuilder newNettyChannelBuilder(String targetUrl, String proxy)
diff --git a/src/test/shell/bazel/remote/BUILD b/src/test/shell/bazel/remote/BUILD index d3848dd..0aa83be 100644 --- a/src/test/shell/bazel/remote/BUILD +++ b/src/test/shell/bazel/remote/BUILD
@@ -47,6 +47,20 @@ size = "large", timeout = "eternal", srcs = ["remote_execution_tls_test.sh"], + args = ["--tls"], + data = [ + "//src/test/shell/bazel:test-deps", + "//src/test/testdata/test_tls_certificate", + "//src/tools/remote:worker", + ], +) + +sh_test( + name = "remote_execution_mtls_test", + size = "large", + timeout = "eternal", + srcs = ["remote_execution_tls_test.sh"], + args = ["--mtls"], data = [ "//src/test/shell/bazel:test-deps", "//src/test/testdata/test_tls_certificate",
diff --git a/src/test/shell/bazel/remote/remote_execution_tls_test.sh b/src/test/shell/bazel/remote/remote_execution_tls_test.sh index c9205b9..2436acb 100755 --- a/src/test/shell/bazel/remote/remote_execution_tls_test.sh +++ b/src/test/shell/bazel/remote/remote_execution_tls_test.sh
@@ -23,12 +23,22 @@ || { echo "integration_test_setup.sh not found!" >&2; exit 1; } cert_path="${BAZEL_RUNFILES}/src/test/testdata/test_tls_certificate" +client_mtls_flags= +enable_mtls=0 +if [[ $1 == "--mtls" ]]; then + enable_mtls=1 + client_mtls_flags="--tls_client_certificate=${cert_path}/client.crt --tls_client_key=${cert_path}/client.pem" +fi function set_up() { work_path=$(mktemp -d "${TEST_TMPDIR}/remote.XXXXXXXX") cas_path=$(mktemp -d "${TEST_TMPDIR}/remote.XXXXXXXX") pid_file=$(mktemp -u "${TEST_TMPDIR}/remote.XXXXXXXX") attempts=1 + mtls_flag= + if [[ $enable_mtls == 1 ]]; then + mtls_flag=--tls_ca_certificate="${cert_path}/ca.crt" + fi while [ $attempts -le 3 ]; do (( attempts++ )) worker_port=$(pick_random_unused_tcp_port) || fail "no port found" @@ -38,6 +48,7 @@ --cas_path=${cas_path} \ --tls_certificate="${cert_path}/server.crt" \ --tls_private_key="${cert_path}/server.pem" \ + $mtls_flag \ --pid_file="${pid_file}" >& $TEST_log & local wait_seconds=0 until [ -s "${pid_file}" ] || [ "$wait_seconds" -eq 15 ]; do @@ -82,10 +93,25 @@ bazel build \ --remote_cache=grpcs://localhost:${worker_port} \ --tls_certificate="${cert_path}/ca.crt" \ + ${client_mtls_flags} \ //a:foo \ || fail "Failed to build //a:foo with grpcs remote cache" } +# Tests that bazel fails if no client cert is provided but the server requires one. +function test_mtls_fails_if_client_has_no_cert() { + # This test only makes sense when we test mtls. + [[ $enable_mtls == 1 ]] || return 0 + _prepareBasicRule + + bazel build \ + --remote_cache=grpcs://localhost:${worker_port} \ + --tls_certificate="${cert_path}/ca.crt" \ + //a:foo 2> $TEST_log \ + && fail "Expected bazel to fail without a client cert" || true + expect_log "ALERT_HANDSHAKE_FAILURE" +} + function test_remote_grpc_cache() { # Test that if default scheme for --remote_cache flag, remote cache works. _prepareBasicRule @@ -93,6 +119,7 @@ bazel build \ --remote_cache=localhost:${worker_port} \ --tls_certificate="${cert_path}/ca.crt" \ + ${client_mtls_flags} \ //a:foo \ || fail "Failed to build //a:foo with grpc remote cache" } @@ -104,6 +131,7 @@ bazel build \ --remote_cache=https://localhost:${worker_port} \ --tls_certificate="${cert_path}/ca.crt" \ + ${client_mtls_flags} \ //a:foo \ || fail "Failed to build //a:foo with https remote cache" } @@ -115,6 +143,7 @@ bazel build \ --remote_cache=grpc://localhost:${worker_port} \ --tls_certificate="${cert_path}/ca.crt" \ + ${client_mtls_flags} \ //a:foo \ && fail "Expected test failure" || true }
diff --git a/src/test/testdata/test_tls_certificate/ca.crt b/src/test/testdata/test_tls_certificate/ca.crt index 0fd16e7..73d3ae5 100644 --- a/src/test/testdata/test_tls_certificate/ca.crt +++ b/src/test/testdata/test_tls_certificate/ca.crt
@@ -1,27 +1,29 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE-----
diff --git a/src/test/testdata/test_tls_certificate/client.crt b/src/test/testdata/test_tls_certificate/client.crt new file mode 100644 index 0000000..4a51444 --- /dev/null +++ b/src/test/testdata/test_tls_certificate/client.crt
@@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEnjCCAoYCAQEwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0 +MCAXDTIwMDMyNjIwMTgxNFoYDzMwMDAwNTI4MjAxODE0WjAUMRIwEAYDVQQDDAls +b2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF54vGUHKl +cxyM6S1FHpReStov6FWvhw1FMi54nkU81aqIOu53shmYM0bbqU2jLKO2wDKG+0Yn +yAMJ/mYeoW3hTSyN6E+Ppa7hzO5pUEE8Bl33c3sECF85YcvHfVdPZjkd6T4bK09h +c/VJGKUTgR0f79SrFxYx9OuMa2Z0R9/0+P99tbECN18rD9nJGBFEcXPr1BNJvED7 +U6d8TujcRS5crsdEsUH31O7y1X5lhpul3wtoGPjj9voue8QtfhDjji3f7tdIGRgu +46qc+THxemFKLrXNwJHP82t0sL6ySZ6e/ZodEN2TXdBB2xtEQppAwmLLRx7sCpqf +FdQ3ZIanlJXjr9JOMhOioxCtq0F6ZYyDnpXJ6qzBZYOjDdy27MEMo7r0SlOTycnh +GfML6GMH4ojgVicOZsIQgQ/8/tHkQKGD5+I9FuhHTKccIRlHqRGW3EvgFWigxY4/ +nO3/henKlIjn2OywYWR4ROHDkRBN9xwDWGWGMy2ljVqdyTmzGYldNopvJUY2Ux6G +FZyeoy3NWjIcKVHzNj+UN9kWSpycB37SbWhTm5V1FXoiH5p6eJAcWr2zLlTRlq6e +5v2Vt47e8DQz9h6d0rniEPQp72RTkyGc5nAgqambGx3MjfCbOUyJZxRlRd+sylPM +qugkM/Vhg1wq52VsRBr6nbGG2b4urM9jYwIDAQABMA0GCSqGSIb3DQEBCwUAA4IC +AQAk0TEreEfh0QeZeXHtY1c3w9A5TPbyThTheUVWDLYNXhv9usKACQ4/jlG3Ybat +2Pxo4xedTQ89xF19CCmB4lthAF2onwYavY+hZOC7IVEfCoA6jZgGpwaw3I0ptug0 +BrQqnBEZFmC8aHqDEgJLgP2tASMQUTl0deNX1rtjvIodaUjPEdyO3QlvPpfq13BM +y544gYy6ppewjDPnObpDz+FrLoNcA5VPIaimgIF8sBcnd/KDC+WJiE5aEHUFKvD2 +aAt23bTRyrwFtyDmEwvZTh44Kyy+FpeJb8Mud+lEcAeb7FpCQkq/Z4JKf5Lq9SZ9 +of/uKThVW5152l+c8t9E6WveDM30lzu3jqUz8RX3li6yb97xPhrKpMxHzh2iJ9AB +MD8u7S7HLllPkXuyEOpLg03XlLS/XzRg+FWm7NcpKhe4v17j0/KgoAaKhdkbLJLZ +vRojvfk+3sQG/R/i92YuqHJ+FzNwqVKJuE1/g737ecuiu8sPSF/ow7w5YaAw3ffo +FYGHUyZTDKYDj7jcbMAxh9VeKhpvIfIdtNP6mbG1IQ4H18G1q+z7TL8HP5ngwPWP +HtO4Z4I4X9vRZ+R1466gbHd1zyZBdu3/SIgGPD567fOebv9n1rqcC6w6Ltc60hto +GVMsFbzqGVU/rGXtHcbE0BII1WLRg0+zgPqw6lVahwoJag== +-----END CERTIFICATE-----
diff --git a/src/test/testdata/test_tls_certificate/client.pem b/src/test/testdata/test_tls_certificate/client.pem new file mode 100644 index 0000000..f48d934 --- /dev/null +++ b/src/test/testdata/test_tls_certificate/client.pem
@@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +onTQcM9+JyAP+7leDL3gbkWSLPxFJg== +-----END PRIVATE KEY-----
diff --git a/src/test/testdata/test_tls_certificate/server.crt b/src/test/testdata/test_tls_certificate/server.crt index 3cfae90..25a9e8a 100644 --- a/src/test/testdata/test_tls_certificate/server.crt +++ b/src/test/testdata/test_tls_certificate/server.crt
@@ -1,27 +1,27 @@ -----BEGIN CERTIFICATE----- -MIIEnjCCAoYCAQEwDQYJKoZIhvcNAQEFBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0 -MCAXDTE5MDQyNTA2NTcxN1oYDzI5OTkwNjI2MDY1NzE3WjAUMRIwEAYDVQQDDAls -b2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDQJwu4CLzB -XHkWUaiW7CpHvUyq8SP3tV3l+havZA+tkdhS+U6mo0xQOIZPSzxmj6xBk7elC42N -0mKKFZQ9ZkErHjmBT0dy/Djlm2dEN8sCN00n74UMWR/QoBygV2hBGgHLGwQ8/9tY -eVxXh84xikIPnCvlAzbWHd+2gN1RI6n7fz1Z0nO6mk6Q7hi5x6XtBnz2908o0VEb -JQYSu0LRL2vu7QYmnJ/1bqM0peq5n+ellCt8qiEmcTcw23jHGqlsyTy9vrJCO0Up -LKZ2SR9wewbAnImZAPDWytQEVpCP6eEiIdNyDvYsTeoUPECklNUi9Iy25gZPeptC -x8YWeZGZXen/Nct416bH8VrYqmjhArXfimUiw/TdREOlvVFmcBpuvTKXKVpvuyIf -XK9mQVg7ITRnXIvJBoapcV0EaaFykCvRMDvGqwiR05da+ZlH6TykJ74BV0y1NFY0 -XJrzhYvGPYF3nP3wDqHd4BJBNecT+26GN5Y3Z0fyBCf52nyhWKU+Cj1bXILNs9wt -A08HL1B09vFpm8TIBYnUDbQQpYumwiN0qzlRuXOR5AfmvFJoVSFvD0BW4itX0nY+ -3ep5Zia4TRbhYOSHPPaln4RfxEWh8ERh9EU3TAPbqv/Rl0HUL4e3kN32pamRH9+8 -7j2bet8BoDngwgyHFYAtD9j/LtmEhRKSzQIDAQABMA0GCSqGSIb3DQEBBQUAA4IC -AQBogMIcx+S+X/hZFCLcZIfGCqDjkscnrEM0pMd3xZJq34ETlwB0gnNC6jVjFgmI -IDcY3ShezLNeMB61p3DPtDm7ILJZgtmtXFzasxuTcvvPg6YPKoz4h1hAmt7BIDDW -nAxUVdm8mYaU1GVzxgqeWsn38tZtr02IwZxpNn4J/tirs/lCB++NnyaIY0HZUVp9 -3XVa1hPv2R4E4lr1hyqHECU5rllM/qMV8sWdg5TVw/TJa3RFmNL7wXUEGxtrlwb1 -kSVjzq+CvUSIzj6MG9EbPhghEQ/GdbmRileUBA4/LXb48eyP8KMgYhxMEX4HQGoX -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 -----END CERTIFICATE-----
diff --git a/src/test/testdata/test_tls_certificate/server.pem b/src/test/testdata/test_tls_certificate/server.pem index 8c5606a..0dec6ed 100644 --- a/src/test/testdata/test_tls_certificate/server.pem +++ b/src/test/testdata/test_tls_certificate/server.pem
@@ -1,52 +1,52 @@ -----BEGIN PRIVATE KEY----- -MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDQJwu4CLzBXHkW -UaiW7CpHvUyq8SP3tV3l+havZA+tkdhS+U6mo0xQOIZPSzxmj6xBk7elC42N0mKK -FZQ9ZkErHjmBT0dy/Djlm2dEN8sCN00n74UMWR/QoBygV2hBGgHLGwQ8/9tYeVxX -h84xikIPnCvlAzbWHd+2gN1RI6n7fz1Z0nO6mk6Q7hi5x6XtBnz2908o0VEbJQYS -u0LRL2vu7QYmnJ/1bqM0peq5n+ellCt8qiEmcTcw23jHGqlsyTy9vrJCO0UpLKZ2 -SR9wewbAnImZAPDWytQEVpCP6eEiIdNyDvYsTeoUPECklNUi9Iy25gZPeptCx8YW -eZGZXen/Nct416bH8VrYqmjhArXfimUiw/TdREOlvVFmcBpuvTKXKVpvuyIfXK9m -QVg7ITRnXIvJBoapcV0EaaFykCvRMDvGqwiR05da+ZlH6TykJ74BV0y1NFY0XJrz -hYvGPYF3nP3wDqHd4BJBNecT+26GN5Y3Z0fyBCf52nyhWKU+Cj1bXILNs9wtA08H -L1B09vFpm8TIBYnUDbQQpYumwiN0qzlRuXOR5AfmvFJoVSFvD0BW4itX0nY+3ep5 -Zia4TRbhYOSHPPaln4RfxEWh8ERh9EU3TAPbqv/Rl0HUL4e3kN32pamRH9+87j2b -et8BoDngwgyHFYAtD9j/LtmEhRKSzQIDAQABAoICAFKCR7jpbbjP6QeZ0tQQRSou -tUdFUtaLw+63VWqspTJOD4vEWxLexA9AeKzRy91zsfpEjZUUoUXIUVse9qXn9Ikc -7/p77Hx90ifhk+uMmiIEvcbIwNqGMYBHF1HPk/nKT0+tI97yJIZLhPkFUgx9G3aI -lzWuMnxpVxZGunPBSU3xv+Xs8AbVx7LXTmHF69WqrrpOichKQHYcFO4z4GZ+/6+z -sK55g0aMVpE1+3cdFXui4iIGZiGQ2ym4tYVm4iXHFxa3kn2CdQW/NzTIA3hYq/KJ -mllV8CGUQLp/fcouERmwgtpBZ/9j2xeuUolqnZm/ik+tmm7C0OyFt9WM1tQOUAQs -0GNJTq/bpnx3igK5qCDrI9nRdVzGHsdZnefKc1QIr/MCEo1kHtFJeHPHGNDIWENW -UpWfI63dA2yKSBAYSz5ictuELF9Xa2uCX9J/D4nZl/J0SoqvFZ2GxADmGajVugBF -RlNbgqSjTSFG+5//GvwBESchaAarwtPaLAkK3M/s8z0BO2vOz7RmyicaarwgbBvn -OBhSOuaIUXAq1qNd3zqpirt+pP6+xo2A+erTqgJ0dGiFDyzhT7anzNA5SVvlBYcg -89aWHdgwcwXCM3ILzmdq8bPIUAp9wi041Bp15rhnKR7m5ZCg69I1p1PLjp87lM71 -omtJ0lWcy+uAU15akdMZAoIBAQDpUhgkk/v7otTAiY0+G8IKVtudOf0xo8Hz/WWs -7EpZIxBgv3x15fsHsg09ORbImd8Q4kvgodvcTzOc5pB7Mr2GXty8i0YfEOl6XzKB -YCAyoI57iNycFu/hfiOuo6pHIe8j2kA3ik5DOxLk3DMyQgCUwpmKZmQT0c62NUMZ -HTvAwfdYqwNmBRLdlVDGEg9atOa6grqC2HjPUmL+hMKlpx+Fx6sb6oWYZDu+4Efg -cdzfyhxYIXFydJ+JttWd8bS/A3C01Y13WWJ5Zwe9awh2YrDYX1uT6IB/stwAnpN/ -W/JB0TCkZlkfsRp7nvSLYu3sOjs+8KCcOPu8Ylof5CXrDgJ3AoIBAQDkYqwHvlUN -Xb86Pavo6tFfIloZMq8U0RGlNXrG+Rm6Z+eTAEyVvnu4ApkD/19N0AGKGdSjkKzb -xt4gOyU/IxHplu1zCJButVx9PiysXpX12KTlsEP0B2f+JHtirWMPCmPrkFsh8l5h -Uls7c8eDABE7+UdQrf63OZMYxRRt3liiasvRTg256M79/JYQJBmKu4NC0UhRpRH5 -LwByeY5QIxXGN1JdmDXTFh2A/UEjLlF+9ZklyDXgU2Aljkf6BAuNlsJ1rABvG3nC -dD0cqO4xVBIacrYTKgL+PULlmTpSdnwILlthEDdxrojj7mZrVPJklzkWsiwVYIEs -+fZ5TLF/jAHbAoIBAQCZZjAZXHI/bz8Rl14Vh4p74b9iD8435MKP9/nxRylakYMj -GMJrgVkaJiYuKmqgWQofv6jDd6dloWz9q1kyppmUzqmyDJ99rVDT8+LwzJJettD2 -x3TD6xCr4JL1LwW03sqrd8LgwT3TVfOGJIBEesCHDaqFI+yIW1jc0wfaay3t/Zjx -4v3JBWzx4knI7/bIXEeWOH0HqetD45bSX9bZspc3DZ+iKv7KwpvFUw/usO3W9LrN -9q7v4V1C3cJ0pYWAUHK5ce4gmdP0nZipIMXfj+NVXtyG0kYprx6WCaxP/9O3EiI4 -9FGEVJxkyo1dVx22QlLRfsMZ8x0PLlqyvP1xHTThAoIBAQCdn1gZlAwBSJVFLfEq -tH3CCeRjBa7+T/i8q/dLwfo2w6V4uDkjFC8w5WIT9zkgbBHT7VXreVtD57HATvG6 -7IpdTBQfU2bTcYoeyj1szW70GQxdldSgZEgqh6U8imwWolYp6xxqhmsLAhsDIjot -OGusl7PXg+6LKEpUSxh5Z36GwexfTV5906agdqZfB3s1W4sRH32pE6Me9oh5eVl2 -B3Dst5u6CuYDBH1iW+eLz1jhpcGH6PD+HKz73oHglNAgbU9ShV5bUHwtb6oJ0LFs -DBjedhMhkNo1+7Pi4Gj3Jt0djFj22YlahVnm7c9z/lG4iQIWnut76Xndv7qTJxJN -9CQHAoIBAD0Lf4U/LI2BeWmGUeCZs70EWg5eKjcfDPq4yscl+ga3q1STO3A7kzJp -rTfNL/pZyEJR0YBL+XEWnTfM9Jk28JE2wUGFLjIpSR5/lT502TPwpanO6/QAsvqz -6Gy5ieygM6iDewVTaB6550JwGndRj1KlDRIOgq9xwCK6zMM7EpvrMRBF9mlO4kh5 -FUd+gpdseE98voURwlFC6A5/D03d3oTBt5wG8CZjplhX0Mnt9S3o77Kx9Odm/jbe -90GuUbJnbRVb9g21bLlc+jcxNTc1VEQmMo/qdQL7HoTE5Igz4yBz3RGpNk5GLbSy -QZdE11Pf2YMgwLAKdkZ1N6pOwQRpLFA= +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 +kFXtZAPNBO0IKMh9aPrUgaiakUeV1pQ= -----END PRIVATE KEY-----
diff --git a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java index e4bd8de..0bd3791 100644 --- a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java +++ b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java
@@ -63,6 +63,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslProvider; import java.io.File; @@ -176,10 +177,14 @@ } private SslContextBuilder getSslContextBuilder(RemoteWorkerOptions workerOptions) { - SslContextBuilder sslClientContextBuilder = + SslContextBuilder sslContextBuilder = SslContextBuilder.forServer( new File(workerOptions.tlsCertificate), new File(workerOptions.tlsPrivateKey)); - return GrpcSslContexts.configure(sslClientContextBuilder, SslProvider.OPENSSL); + if (workerOptions.tlsCaCertificate != null) { + sslContextBuilder.clientAuth(ClientAuth.REQUIRE); + sslContextBuilder.trustManager(new File(workerOptions.tlsCaCertificate)); + } + return GrpcSslContexts.configure(sslContextBuilder, SslProvider.OPENSSL); } private void createPidFile() throws IOException {
diff --git a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorkerOptions.java b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorkerOptions.java index c6b876a..78a040f 100644 --- a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorkerOptions.java +++ b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorkerOptions.java
@@ -166,6 +166,16 @@ help = "Specify the TLS private key to be used.") public String tlsPrivateKey; + @Option( + name = "tls_ca_certificate", + defaultValue = "null", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.UNKNOWN}, + help = + "Specify a CA certificate to use for authenticating clients; setting this implicitly " + + "requires client authentication (aka mTLS).") + public String tlsCaCertificate; + private static final int MAX_JOBS = 16384; /**