Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type RunConfig struct {
Namespace string
ClientCertPath string
ClientKeyPath string
CACertPath string
TLSServerName string
GenerateHistory bool
DisableHistoryCheck bool
Expand Down Expand Up @@ -93,6 +94,11 @@ func (r *RunConfig) dockerRunFlags() []cli.Flag {
Usage: "Path of TLS client key to use (optional)",
Destination: &r.ClientKeyPath,
},
&cli.StringFlag{
Name: "ca-cert-path",
Usage: "Path of CA cert to use for server verification (optional)",
Destination: &r.CACertPath,
},
&cli.StringFlag{
Name: "tls-server-name",
Usage: "TLS server name to use for verification and SNI override (optional)",
Expand Down Expand Up @@ -244,7 +250,7 @@ func (r *Runner) Run(ctx context.Context, patterns []string) error {
} else {
// Wait for namespace to become available
err := harness.WaitNamespaceAvailable(ctx, r.log,
r.config.Server, r.config.Namespace, r.config.ClientCertPath, r.config.ClientKeyPath, r.config.TLSServerName)
r.config.Server, r.config.Namespace, r.config.ClientCertPath, r.config.ClientKeyPath, r.config.CACertPath, r.config.TLSServerName)
if err != nil {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/run_dotnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ func (r *Runner) RunDotNetExternal(ctx context.Context, run *cmd.Run) error {
if r.config.ClientCertPath != "" {
args = append(args, "--client-cert-path", r.config.ClientCertPath, "--client-key-path", r.config.ClientKeyPath)
}
if r.config.CACertPath != "" {
args = append(args, "--ca-cert-path", r.config.CACertPath)
}
if r.config.HTTPProxyURL != "" {
args = append(args, "--http-proxy-url", r.config.HTTPProxyURL)
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/run_go.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ func (r *Runner) RunGoExternal(ctx context.Context, run *cmd.Run) error {
"--client-key-path", r.config.ClientKeyPath,
"--summary-uri", r.config.SummaryURI,
}
if r.config.CACertPath != "" {
args = append(args, "--ca-cert-path", r.config.CACertPath)
}
if r.config.HTTPProxyURL != "" {
args = append(args, "--http-proxy-url", r.config.HTTPProxyURL)
}
Expand Down
7 changes: 7 additions & 0 deletions cmd/run_java.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ func (r *Runner) RunJavaExternal(ctx context.Context, run *cmd.Run) error {
}
args = append(args, "--client-key-path", clientKeyPath)
}
if r.config.CACertPath != "" {
caCertPath, err := filepath.Abs(r.config.CACertPath)
if err != nil {
return err
}
args = append(args, "--ca-cert-path", caCertPath)
}
if r.config.SummaryURI != "" {
args = append(args, "--summary-uri", r.config.SummaryURI)
}
Expand Down
8 changes: 8 additions & 0 deletions cmd/run_php.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"path/filepath"

"github.com/temporalio/features/harness/go/cmd"
"github.com/temporalio/features/sdkbuild"
)
Expand Down Expand Up @@ -63,6 +64,13 @@ func (r *Runner) RunPhpExternal(ctx context.Context, run *cmd.Run) error {
}
args = append(args, "tls.key="+clientKeyPath)
}
if r.config.CACertPath != "" {
caCertPath, err := filepath.Abs(r.config.CACertPath)
if err != nil {
return err
}
args = append(args, "tls.ca-cert="+caCertPath)
}
if r.config.TLSServerName != "" {
args = append(args, "tls.server-name="+r.config.TLSServerName)
}
Expand Down
7 changes: 7 additions & 0 deletions cmd/run_python.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ func (r *Runner) RunPythonExternal(ctx context.Context, run *cmd.Run) error {
}
args = append(args, "--client-key-path", clientKeyPath)
}
if r.config.CACertPath != "" {
caCertPath, err := filepath.Abs(r.config.CACertPath)
if err != nil {
return err
}
args = append(args, "--ca-cert-path", caCertPath)
}
if r.config.HTTPProxyURL != "" {
args = append(args, "--http-proxy-url", r.config.HTTPProxyURL)
}
Expand Down
7 changes: 7 additions & 0 deletions cmd/run_typescript.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ func (r *Runner) RunTypeScriptExternal(ctx context.Context, run *cmd.Run) error
}
args = append(args, "--client-key-path", clientKeyPath)
}
if r.config.CACertPath != "" {
caCertPath, err := filepath.Abs(r.config.CACertPath)
if err != nil {
return err
}
args = append(args, "--ca-cert-path", caCertPath)
}
if r.config.HTTPProxyURL != "" {
args = append(args, "--http-proxy-url", r.config.HTTPProxyURL)
}
Expand Down
8 changes: 7 additions & 1 deletion features/client/http_proxy/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func (h HTTPProxyTest) Execute(ctx context.Context, r *harness.Runner) (client.W
namespace: r.Namespace,
clientCertPath: r.ClientCertPath,
clientKeyPath: r.ClientKeyPath,
caCertPath: r.CACertPath,
tlsServerName: r.TLSServerName,
taskQueue: r.TaskQueue,
workflowID: "wf-" + uuid.NewString(),
Expand Down Expand Up @@ -94,7 +95,7 @@ func SubprocessExecuteWorkflow(ctx context.Context, args *subprocessArgs) error
clientOpts := client.Options{HostPort: fmt.Sprintf("passthrough:///%s", args.server), Namespace: args.namespace}
if args.clientCertPath != "" {
var err error
clientOpts.ConnectionOptions.TLS, err = harness.LoadTLSConfig(args.clientCertPath, args.clientKeyPath, args.tlsServerName)
clientOpts.ConnectionOptions.TLS, err = harness.LoadTLSConfig(args.clientCertPath, args.clientKeyPath, args.caCertPath, args.tlsServerName)
if err != nil {
return fmt.Errorf("failed loading TLS config: %w", err)
}
Expand Down Expand Up @@ -139,6 +140,7 @@ type subprocessArgs struct {
namespace string
clientCertPath string
clientKeyPath string
caCertPath string
tlsServerName string
taskQueue string
workflowID string
Expand All @@ -151,6 +153,7 @@ func (s *subprocessArgs) flags() []cli.Flag {
&cli.StringFlag{Name: "namespace", Destination: &s.namespace, Required: true},
&cli.StringFlag{Name: "client-cert-path", Destination: &s.clientCertPath},
&cli.StringFlag{Name: "client-key-path", Destination: &s.clientKeyPath},
&cli.StringFlag{Name: "ca-cert-path", Destination: &s.caCertPath},
&cli.StringFlag{Name: "tls-server-name", Destination: &s.tlsServerName},
&cli.StringFlag{Name: "task-queue", Destination: &s.taskQueue, Required: true},
&cli.StringFlag{Name: "workflow-id", Destination: &s.workflowID, Required: true},
Expand All @@ -167,6 +170,9 @@ func (s *subprocessArgs) args() []string {
if s.clientCertPath != "" {
args = append(args, "--client-cert-path", s.clientCertPath, "--client-key-path", s.clientKeyPath)
}
if s.caCertPath != "" {
args = append(args, "--ca-cert-path", s.caCertPath)
}
if s.tlsServerName != "" {
args = append(args, "--tls-server-name", s.tlsServerName)
}
Expand Down
4 changes: 3 additions & 1 deletion features/update/self/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type ConnMaterial struct {
Identity string
ClientCertPath string
ClientKeyPath string
CACertPath string
TLSServerName string
}

Expand All @@ -45,6 +46,7 @@ var Feature = harness.Feature{
Identity: runner.Feature.ClientOptions.Identity,
ClientCertPath: runner.ClientCertPath,
ClientKeyPath: runner.ClientKeyPath,
CACertPath: runner.CACertPath,
TLSServerName: runner.TLSServerName,
})
},
Expand Down Expand Up @@ -77,7 +79,7 @@ func SelfUpdateWorkflow(ctx workflow.Context, cm ConnMaterial) (string, error) {
}

func SelfUpdateActivity(ctx context.Context, cm ConnMaterial) error {
tlsCfg, err := harness.LoadTLSConfig(cm.ClientCertPath, cm.ClientKeyPath, cm.TLSServerName)
tlsCfg, err := harness.LoadTLSConfig(cm.ClientCertPath, cm.ClientKeyPath, cm.CACertPath, cm.TLSServerName)
if err != nil {
return err
}
Expand Down
9 changes: 9 additions & 0 deletions harness/dotnet/Temporalio.Features.Harness/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public static class App
name: "--client-key-path",
description: "Path to a client key for TLS");

private static readonly Option<FileInfo?> caCertPathOption = new(
name: "--ca-cert-path",
description: "Path to a CA certificate for server verification");

private static readonly Option<string?> httpProxyUrlOption = new(
name: "--http-proxy-url",
description: "HTTP proxy URL");
Expand Down Expand Up @@ -64,6 +68,7 @@ private static Command CreateCommand()
cmd.AddOption(namespaceOption);
cmd.AddOption(clientCertPathOption);
cmd.AddOption(clientKeyPathOption);
cmd.AddOption(caCertPathOption);
cmd.AddOption(httpProxyUrlOption);
cmd.AddOption(tlsServerNameOption);
cmd.AddArgument(featuresArgument);
Expand Down Expand Up @@ -95,6 +100,10 @@ private static async Task RunCommandAsync(InvocationContext ctx)
ctx.ParseResult.GetValueForOption(clientKeyPathOption)?.FullName ??
throw new ArgumentException("Missing key with cert"))
};
if (ctx.ParseResult.GetValueForOption(caCertPathOption) is { } caCertPath)
{
tlsOptions.ServerRootCACert = File.ReadAllBytes(caCertPath.FullName);
}
if (!string.IsNullOrEmpty(tlsServerName))
{
tlsOptions.Domain = tlsServerName;
Expand Down
6 changes: 6 additions & 0 deletions harness/go/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ type RunConfig struct {
Namespace string
ClientCertPath string
ClientKeyPath string
CACertPath string
SummaryURI string
HTTPProxyURL string
TLSServerName string
Expand Down Expand Up @@ -119,6 +120,11 @@ func (r *RunConfig) flags() []cli.Flag {
Usage: "Path of TLS client key to use (optional)",
Destination: &r.ClientKeyPath,
},
&cli.StringFlag{
Name: "ca-cert-path",
Usage: "Path of CA cert to use for server verification (optional)",
Destination: &r.CACertPath,
},
&cli.StringFlag{
Name: "summary-uri",
Usage: "where to stream the test summary JSONL",
Expand Down
3 changes: 2 additions & 1 deletion harness/go/harness/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type RunnerConfig struct {
TaskQueue string
ClientCertPath string
ClientKeyPath string
CACertPath string
Log log.Logger
HTTPProxyURL string
TLSServerName string
Expand Down Expand Up @@ -90,7 +91,7 @@ func NewRunner(config RunnerConfig, feature *PreparedFeature) (*Runner, error) {
r.Feature.ClientOptions.Logger = r.Log
}
var err error
tlsCfg, err := LoadTLSConfig(r.ClientCertPath, r.ClientKeyPath, r.TLSServerName)
tlsCfg, err := LoadTLSConfig(r.ClientCertPath, r.ClientKeyPath, r.CACertPath, r.TLSServerName)
if err != nil {
return nil, err
}
Expand Down
21 changes: 18 additions & 3 deletions harness/go/harness/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package harness
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -130,7 +131,7 @@ func GetCountCompletedUpdates(ctx context.Context, client client.Client, workflo

// WaitNamespaceAvailable waits for up to 5 seconds for the provided namespace to become available
func WaitNamespaceAvailable(ctx context.Context, logger log.Logger,
hostPortStr, namespace, clientCertPath, clientKeyPath, tlsServerName string) error {
hostPortStr, namespace, clientCertPath, clientKeyPath, caCertPath, tlsServerName string) error {
logger.Info("Waiting for namespace to become available", "namespace", namespace)

var myClient client.Client
Expand All @@ -139,7 +140,7 @@ func WaitNamespaceAvailable(ctx context.Context, logger log.Logger,
myClient.Close()
}
}()
tlsCfg, err := LoadTLSConfig(clientCertPath, clientKeyPath, tlsServerName)
tlsCfg, err := LoadTLSConfig(clientCertPath, clientKeyPath, caCertPath, tlsServerName)
if err != nil {
return err
}
Expand Down Expand Up @@ -229,7 +230,7 @@ func RetryFor(maxAttempts int, interval time.Duration, cond func() (bool, error)
}

// LoadTLSConfig inits a TLS config from the provided cert and key files.
func LoadTLSConfig(clientCertPath, clientKeyPath, tlsServerName string) (*tls.Config, error) {
func LoadTLSConfig(clientCertPath, clientKeyPath, caCertPath, tlsServerName string) (*tls.Config, error) {
if clientCertPath != "" {
if clientKeyPath == "" {
return nil, errors.New("got TLS cert with no key")
Expand All @@ -239,6 +240,20 @@ func LoadTLSConfig(clientCertPath, clientKeyPath, tlsServerName string) (*tls.Co
return nil, fmt.Errorf("failed to load certs: %s", err)
}
tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}, ServerName: tlsServerName}

// Load CA cert if provided
if caCertPath != "" {
caCert, err := os.ReadFile(caCertPath)
if err != nil {
return nil, fmt.Errorf("failed to read CA cert: %s", err)
}
caCertPool := x509.NewCertPool()
if !caCertPool.AppendCertsFromPEM(caCert) {
return nil, errors.New("failed to parse CA cert")
}
tlsConfig.RootCAs = caCertPool
}

return tlsConfig, nil
} else if clientKeyPath != "" {
return nil, errors.New("got TLS key with no cert")
Expand Down
36 changes: 33 additions & 3 deletions harness/java/io/temporal/sdkfeatures/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@
import java.io.*;
import java.net.Socket;
import java.net.URI;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
Expand Down Expand Up @@ -86,6 +90,9 @@ BufferedWriter createSummaryServerWriter() {
@Option(names = "--client-key-path", description = "Path to a client key for TLS")
private String clientKeyPath;

@Option(names = "--ca-cert-path", description = "Path to a CA cert for server verification")
private String caCertPath;

@Option(names = "--http-proxy-url", description = "URL for an HTTP CONNECT proxy to the server")
private String httpProxyUrl;

Expand All @@ -107,8 +114,31 @@ public void run() {
try {
InputStream clientCert = new FileInputStream(clientCertPath);
InputStream clientKey = new FileInputStream(clientKeyPath);
sslContext = SimpleSslContextBuilder.forPKCS8(clientCert, clientKey).build();
} catch (FileNotFoundException | SSLException e) {
SimpleSslContextBuilder builder = SimpleSslContextBuilder.forPKCS8(clientCert, clientKey);

if (StringUtils.isNotEmpty(caCertPath)) {
// Load CA certificate and create a TrustManager
InputStream caCertStream = new FileInputStream(caCertPath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) cf.generateCertificate(caCertStream);
caCertStream.close();

KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
trustStore.setCertificateEntry("temporal-ca", caCert);

TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
TrustManager[] trustManagers = tmf.getTrustManagers();

if (trustManagers.length > 0) {
builder.setTrustManager(trustManagers[0]);
}
}

sslContext = builder.build();
} catch (Exception e) {
throw new RuntimeException("Error loading certs", e);
}

Expand Down
3 changes: 3 additions & 0 deletions harness/php/runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
if ($runtime->command->tlsServerName !== null) {
$sslParams['overrideServerName'] = $runtime->command->tlsServerName;
}
if ($runtime->command->tlsCaCert !== null) {
$sslParams['crt'] = $runtime->command->tlsCaCert;
}
$serviceClient = ServiceClient::createSSL(...$sslParams);
}
echo "Connecting to Temporal service at {$runtime->address}... ";
Expand Down
Loading
Loading