Skip to content

Commit e5efa17

Browse files
committed
SAmple test
1 parent 4ec66e0 commit e5efa17

File tree

5 files changed

+630
-6
lines changed

5 files changed

+630
-6
lines changed

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ PROGS = helloworld \
3737
sideeffect \
3838
sleep \
3939
dataconverter \
40+
tls \
4041

4142
TEST_ARG ?= -race -v -timeout 5m
4243
BUILD := ./build
@@ -72,6 +73,7 @@ TEST_DIRS=./cmd/samples/cron \
7273
./cmd/samples/recipes/signalcounter \
7374
./cmd/samples/recipes/sleep \
7475
./cmd/samples/recipes/dataconverter \
76+
./cmd/samples/recipes/tls \
7577
./cmd/samples/recovery \
7678
./cmd/samples/pso \
7779

@@ -186,6 +188,9 @@ versioning:
186188
dataconverter:
187189
go build -o bin/dataconverter cmd/samples/recipes/dataconverter/*.go
188190

191+
tls:
192+
go build -o bin/tls cmd/samples/recipes/tls/*.go
193+
189194
bins: helloworld \
190195
versioning \
191196
delaystart \
@@ -219,6 +224,7 @@ bins: helloworld \
219224
sideeffect \
220225
sleep \
221226
dataconverter \
227+
tls \
222228

223229
test: bins
224230
@rm -f test

cmd/samples/common/factory.go

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package common
22

33
import (
4+
"crypto/tls"
5+
"crypto/x509"
46
"errors"
7+
"io/ioutil"
58

69
"github.com/opentracing/opentracing-go"
710
"github.com/uber-go/tally"
@@ -12,8 +15,11 @@ import (
1215
"go.uber.org/cadence/encoded"
1316
"go.uber.org/cadence/workflow"
1417
"go.uber.org/yarpc"
18+
"go.uber.org/yarpc/peer"
19+
"go.uber.org/yarpc/peer/hostport"
1520
"go.uber.org/yarpc/transport/grpc"
1621
"go.uber.org/zap"
22+
"google.golang.org/grpc/credentials"
1723
)
1824

1925
const (
@@ -32,6 +38,10 @@ type WorkflowClientBuilder struct {
3238
ctxProps []workflow.ContextPropagator
3339
dataConverter encoded.DataConverter
3440
tracer opentracing.Tracer
41+
tlsConfig *tls.Config
42+
clientCertPath string
43+
clientKeyPath string
44+
caCertPath string
3545
}
3646

3747
// NewBuilder creates a new WorkflowClientBuilder
@@ -89,6 +99,20 @@ func (b *WorkflowClientBuilder) SetTracer(tracer opentracing.Tracer) *WorkflowCl
8999
return b
90100
}
91101

102+
// SetTLSConfig sets the TLS configuration for the builder
103+
func (b *WorkflowClientBuilder) SetTLSConfig(tlsConfig *tls.Config) *WorkflowClientBuilder {
104+
b.tlsConfig = tlsConfig
105+
return b
106+
}
107+
108+
// SetTLSCertificates sets the TLS certificate paths for the builder
109+
func (b *WorkflowClientBuilder) SetTLSCertificates(clientCertPath, clientKeyPath, caCertPath string) *WorkflowClientBuilder {
110+
b.clientCertPath = clientCertPath
111+
b.clientKeyPath = clientKeyPath
112+
b.caCertPath = caCertPath
113+
return b
114+
}
115+
92116
// BuildCadenceClient builds a client to cadence service
93117
func (b *WorkflowClientBuilder) BuildCadenceClient() (client.Client, error) {
94118
service, err := b.BuildServiceClient()
@@ -163,12 +187,42 @@ func (b *WorkflowClientBuilder) build() error {
163187
zap.String("ServiceName", _cadenceFrontendService),
164188
zap.String("HostPort", b.hostPort))
165189

166-
b.dispatcher = yarpc.NewDispatcher(yarpc.Config{
167-
Name: _cadenceClientName,
168-
Outbounds: yarpc.Outbounds{
169-
_cadenceFrontendService: {Unary: grpc.NewTransport().NewSingleOutbound(b.hostPort)},
170-
},
171-
})
190+
// Check if TLS is configured
191+
if b.tlsConfig != nil || (b.clientCertPath != "" && b.clientKeyPath != "" && b.caCertPath != "") {
192+
// Build TLS configuration if certificate paths are provided but tlsConfig is not
193+
if b.tlsConfig == nil {
194+
tlsConfig, err := b.buildTLSConfig()
195+
if err != nil {
196+
return err
197+
}
198+
b.tlsConfig = tlsConfig
199+
}
200+
201+
// Create TLS-enabled gRPC transport
202+
grpcTransport := grpc.NewTransport()
203+
var dialOptions []grpc.DialOption
204+
205+
creds := credentials.NewTLS(b.tlsConfig)
206+
dialOptions = append(dialOptions, grpc.DialerCredentials(creds))
207+
208+
dialer := grpcTransport.NewDialer(dialOptions...)
209+
outbound := grpcTransport.NewOutbound(peer.NewSingle(hostport.PeerIdentifier(b.hostPort), dialer))
210+
211+
b.dispatcher = yarpc.NewDispatcher(yarpc.Config{
212+
Name: _cadenceClientName,
213+
Outbounds: yarpc.Outbounds{
214+
_cadenceFrontendService: {Unary: outbound},
215+
},
216+
})
217+
} else {
218+
// Create standard non-TLS dispatcher
219+
b.dispatcher = yarpc.NewDispatcher(yarpc.Config{
220+
Name: _cadenceClientName,
221+
Outbounds: yarpc.Outbounds{
222+
_cadenceFrontendService: {Unary: grpc.NewTransport().NewSingleOutbound(b.hostPort)},
223+
},
224+
})
225+
}
172226

173227
if b.dispatcher != nil {
174228
if err := b.dispatcher.Start(); err != nil {
@@ -178,3 +232,30 @@ func (b *WorkflowClientBuilder) build() error {
178232

179233
return nil
180234
}
235+
236+
// buildTLSConfig creates a TLS configuration from certificate paths
237+
func (b *WorkflowClientBuilder) buildTLSConfig() (*tls.Config, error) {
238+
// Present client cert for mutual TLS (if enabled on server)
239+
clientCert, err := tls.LoadX509KeyPair(b.clientCertPath, b.clientKeyPath)
240+
if err != nil {
241+
b.Logger.Fatal("Failed to load client certificate: %v", zap.Error(err))
242+
return nil, err
243+
}
244+
245+
// Load server CA
246+
caCert, err := ioutil.ReadFile(b.caCertPath)
247+
if err != nil {
248+
b.Logger.Fatal("Failed to load server CA certificate: %v", zap.Error(err))
249+
return nil, err
250+
}
251+
caCertPool := x509.NewCertPool()
252+
caCertPool.AppendCertsFromPEM(caCert)
253+
254+
tlsConfig := &tls.Config{
255+
InsecureSkipVerify: true,
256+
RootCAs: caCertPool,
257+
Certificates: []tls.Certificate{clientCert},
258+
}
259+
260+
return tlsConfig, nil
261+
}

cmd/samples/recipes/tls/README.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# TLS Connection Verification Recipe
2+
3+
This recipe demonstrates how to verify TLS connections between Cadence SDK and frontend using a Cadence workflow, showing both successful and unsuccessful scenarios.
4+
5+
## What This Recipe Shows
6+
7+
1. **TLS Workflow Execution** - Orchestrates TLS testing using Cadence workflow and activities
8+
2. **Certificate Management** - Automated certificate creation and cleanup
9+
3. **TLS Connection Testing** - Tests connections with valid certificates
10+
4. **Error Handling** - Tests connections with missing certificates
11+
5. **Standard Connection Fallback** - Tests non-TLS connections
12+
13+
## Prerequisites
14+
15+
- Cadence server running on `localhost:7933`
16+
- OpenSSL installed for certificate generation
17+
- Go environment set up
18+
19+
## Steps to Run Sample
20+
21+
1. You need a cadence service running. See details in cmd/samples/README.md
22+
23+
2. Run the following command to start the worker:
24+
```
25+
./bin/tls -m worker
26+
```
27+
28+
3. Run the following command to execute the workflow:
29+
```
30+
./bin/tls -m trigger
31+
```
32+
33+
## Workflow Structure
34+
35+
The recipe follows the standard Cadence worker/trigger pattern:
36+
37+
- **Worker Mode**: Starts a Cadence worker that can execute the TLS workflow and activities
38+
- **Trigger Mode**: Triggers a new execution of the TLS workflow
39+
40+
## Activities
41+
42+
1. **setupCertificatesActivity** - Creates fresh TLS certificates for testing
43+
2. **testTLSConnectionActivity** - Tests TLS connections with provided certificates
44+
3. **testStandardConnectionActivity** - Tests standard non-TLS connections
45+
4. **cleanupCertificatesActivity** - Cleans up generated certificates
46+
47+
## Expected Workflow Output
48+
49+
When you run the trigger mode, the workflow will execute and you'll see logs showing:
50+
51+
```
52+
INFO TLS Workflow started
53+
INFO Setting up certificates for testing
54+
INFO Certificates setup completed
55+
INFO Testing TLS connection with valid certificates
56+
INFO Valid TLS connection test result: SUCCESS - TLS connection established
57+
INFO Testing TLS connection with missing certificates
58+
INFO Missing certificates test failed as expected
59+
INFO Testing standard non-TLS connection
60+
INFO Standard connection test result: SUCCESS - Standard connection established
61+
INFO Cleaning up certificates
62+
INFO Certificate cleanup completed
63+
INFO TLS Workflow completed successfully
64+
```
65+
66+
## Certificate Management
67+
68+
The workflow automatically:
69+
- Creates a `cmd/samples/recipes/tls/certs/` directory
70+
- Generates CA, server, and client certificates using OpenSSL
71+
- Tests connections with the generated certificates
72+
- Cleans up all certificate files after testing
73+
74+
Generated certificates include:
75+
- `ca.key` / `ca.crt` - Certificate Authority
76+
- `server.key` / `server.crt` - Server certificates
77+
- `client.key` / `client.crt` - Client certificates
78+
79+
## Key Features
80+
81+
- **Workflow Orchestration**: Uses Cadence workflow to coordinate TLS testing
82+
- **Automated Certificate Generation**: No manual certificate setup required
83+
- **Comprehensive Testing**: Tests multiple TLS scenarios in sequence
84+
- **Error Handling**: Graceful handling of connection failures
85+
- **Clean Resource Management**: Automatic cleanup of generated certificates
86+
- **Production Patterns**: Demonstrates proper Cadence workflow and activity patterns
87+
88+
## Code Structure
89+
90+
### Main Components
91+
- `main.go` - Worker/trigger entry point following Cadence patterns
92+
- `tls_workflow.go` - Workflow and activity definitions
93+
94+
### Key Functions
95+
- `tlsWorkflow()` - Main workflow that orchestrates TLS testing
96+
- `setupCertificatesActivity()` - Activity to create test certificates
97+
- `testTLSConnectionActivity()` - Activity to test TLS connections
98+
- `testStandardConnectionActivity()` - Activity to test non-TLS connections
99+
- `cleanupCertificatesActivity()` - Activity to clean up certificates
100+
- `createTLSClient()` - Helper to create TLS-enabled Cadence client
101+
102+
This recipe demonstrates how to integrate TLS configuration testing into Cadence workflows, making it suitable for production environments where TLS verification is part of automated testing or deployment processes.

0 commit comments

Comments
 (0)