Skip to content

Commit f6b4ce7

Browse files
Added an example on how to use an SSL Connection with RedisAI (#12)
* [add] Added an example on how to use an SSL Connection with RedisAI * [add] building the examples as part of the main build process
1 parent e06f13e commit f6b4ce7

File tree

6 files changed

+340
-17
lines changed

6 files changed

+340
-17
lines changed

.circleci/config.yml

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,46 @@
33
# Check https://circleci.com/docs/2.0/language-go/ for more details
44
version: 2
55
jobs:
6+
build-tls:
7+
machine:
8+
enabled: true
9+
image: ubuntu-1604:202004-01
10+
steps:
11+
- checkout
12+
- run:
13+
name: Setting GOPATH
14+
command: |
15+
go version
16+
go env -w GOPATH=$HOME/go
17+
- run:
18+
name: Generate a root CA and a server certificate using redis helpers
19+
command: |
20+
git clone git://github.com/antirez/redis.git --branch 6.0.1
21+
cd redis
22+
./utils/gen-test-certs.sh
23+
cd ..
24+
- run:
25+
name: Copy RedisAI
26+
command: |
27+
docker run --rm --entrypoint cat redisai/redisai:edge /usr/lib/redis/modules/redisai.so > redisai.so
28+
chmod 755 redisai.so
29+
- run:
30+
name: Run RedisAI with tls support
31+
command: |
32+
docker run -d -v $(pwd)/redisai.so:/data/redisai.so \
33+
-v $(pwd)/redis/tests/tls/:/data \
34+
-p 6379:6379 redis redis-server --tls-port 6379 --port 0 \
35+
--tls-cert-file /data/redis.crt \
36+
--tls-key-file /data/redis.key \
37+
--tls-ca-cert-file /data/ca.crt \
38+
--tls-auth-clients no --loadmodule /data/redisai.so
39+
- run:
40+
name: Run Examples
41+
command: |
42+
make examples TLS_CERT=redis/tests/tls/redis.crt \
43+
TLS_KEY=redis/tests/tls/redis.key \
44+
TLS_CACERT=redis/tests/tls/ca.crt
45+
646
build-edge: # test with redisai:edge
747
docker:
848
- image: circleci/golang:1.13
@@ -20,6 +60,7 @@ workflows:
2060
commit:
2161
jobs:
2262
- build-edge
63+
- build-tls
2364
nightly:
2465
triggers:
2566
- schedule:
@@ -29,4 +70,5 @@ workflows:
2970
only:
3071
- master
3172
jobs:
32-
- build-edge
73+
- build-edge
74+
- build-tls

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,10 @@
1919

2020
coverage.txt
2121

22+
# Examples
23+
examples/redisai_tls_client/redisai_tls_client
24+
redisai_pipelined_client
25+
examples/redisai_simple_client/redisai_simple_client
26+
redisai_simple_client
27+
examples/redisai_pipelined_client/redisai_pipelined_client
28+
redisai_tls_client

Makefile

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,26 @@ GOGET=$(GOCMD) get
88
GOMOD=$(GOCMD) mod
99

1010
.PHONY: all test coverage
11-
all: test coverage
11+
all: test coverage examples
1212

1313
get:
14-
$(GOGET) -t -v ./...
14+
$(GOGET) -t -v ./redisai/...
15+
16+
TLS_CERT ?= redis.crt
17+
TLS_KEY ?= redis.key
18+
TLS_CACERT ?= ca.crt
19+
REDISAI_TEST_HOST ?= 127.0.0.1:6379
20+
21+
examples: get
22+
@echo " "
23+
@echo "Building the examples..."
24+
$(GOBUILD) ./examples/redisai_pipelined_client/.
25+
$(GOBUILD) ./examples/redisai_simple_client/.
26+
$(GOBUILD) ./examples/redisai_tls_client/.
27+
./redisai_tls_client --tls-cert-file $(TLS_CERT) \
28+
--tls-key-file $(TLS_KEY) \
29+
--tls-ca-cert-file $(TLS_CACERT) \
30+
--host $(REDISAI_TEST_HOST)
1531

1632
test: get
1733
$(GOTEST) -race -covermode=atomic ./...
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package main
2+
3+
import (
4+
"crypto/tls"
5+
"crypto/x509"
6+
"flag"
7+
"fmt"
8+
"github.com/RedisAI/redisai-go/redisai"
9+
"github.com/gomodule/redigo/redis"
10+
"io/ioutil"
11+
"log"
12+
"os"
13+
)
14+
15+
var (
16+
tlsCertFile = flag.String("tls-cert-file", "redis.crt", "A a X.509 certificate to use for authenticating the server to connected clients, masters or cluster peers. The file should be PEM formatted.")
17+
tlsKeyFile = flag.String("tls-key-file", "redis.key", "A a X.509 privat ekey to use for authenticating the server to connected clients, masters or cluster peers. The file should be PEM formatted.")
18+
tlsCaCertFile = flag.String("tls-ca-cert-file", "ca.crt", "A PEM encoded CA's certificate file.")
19+
host = flag.String("host", "127.0.0.1:6379", "Redis host.")
20+
password = flag.String("password", "", "Redis password.")
21+
)
22+
23+
func exists(filename string) (exists bool) {
24+
exists = false
25+
info, err := os.Stat(filename)
26+
if os.IsNotExist(err) || info.IsDir() {
27+
return
28+
}
29+
exists = true
30+
return
31+
}
32+
33+
/*
34+
* Example of how to establish an SSL connection from your app to the RedisAI Server
35+
*/
36+
func main() {
37+
flag.Parse()
38+
// Quickly check if the files exist
39+
if !exists(*tlsCertFile) || !exists(*tlsKeyFile) || !exists(*tlsCaCertFile) {
40+
fmt.Println("Some of the required files does not exist. Leaving example...")
41+
return
42+
}
43+
44+
// Load client cert
45+
cert, err := tls.LoadX509KeyPair(*tlsCertFile, *tlsKeyFile)
46+
if err != nil {
47+
log.Fatal(err)
48+
}
49+
50+
// Load CA cert
51+
caCert, err := ioutil.ReadFile(*tlsCaCertFile)
52+
if err != nil {
53+
log.Fatal(err)
54+
}
55+
caCertPool := x509.NewCertPool()
56+
caCertPool.AppendCertsFromPEM(caCert)
57+
58+
clientTLSConfig := &tls.Config{
59+
Certificates: []tls.Certificate{cert},
60+
RootCAs: caCertPool,
61+
}
62+
63+
// InsecureSkipVerify controls whether a client verifies the
64+
// server's certificate chain and host name.
65+
// If InsecureSkipVerify is true, TLS accepts any certificate
66+
// presented by the server and any host name in that certificate.
67+
// In this mode, TLS is susceptible to man-in-the-middle attacks.
68+
// This should be used only for testing.
69+
clientTLSConfig.InsecureSkipVerify = true
70+
71+
pool := &redis.Pool{Dial: func() (redis.Conn, error) {
72+
return redis.Dial("tcp", *host,
73+
redis.DialPassword(*password),
74+
redis.DialTLSConfig(clientTLSConfig),
75+
redis.DialUseTLS(true),
76+
redis.DialTLSSkipVerify(true),
77+
)
78+
}}
79+
80+
// create a connection from Pool
81+
client := redisai.Connect("", pool)
82+
83+
// Set a tensor
84+
// AI.TENSORSET foo FLOAT 2 2 VALUES 1.1 2.2 3.3 4.4
85+
_ = client.TensorSet("foo", redisai.TypeFloat, []int{2, 2}, []float32{1.1, 2.2, 3.3, 4.4})
86+
87+
// Get a tensor content as a slice of values
88+
// dt DataType, shape []int, data interface{}, err error
89+
// AI.TENSORGET foo VALUES
90+
_, _, fooTensorValues, err := client.TensorGetValues("foo")
91+
92+
if err != nil {
93+
log.Fatal(err)
94+
}
95+
96+
fmt.Println(fooTensorValues)
97+
//Output: [1.1 2.2 3.3 4.4]
98+
}

redisai/client_test.go

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,22 @@ import (
88
"time"
99
)
1010

11-
func createPool() *redis.Pool {
11+
func getConnectionDetails() (host string, password string) {
1212
value, exists := os.LookupEnv("REDISAI_TEST_HOST")
13-
host := "redis://localhost:6379"
13+
host = "redis://127.0.0.1:6379"
14+
password = ""
15+
valuePassword, existsPassword := os.LookupEnv("REDISAI_TEST_PASSWORD")
1416
if exists && value != "" {
1517
host = value
1618
}
19+
if existsPassword && valuePassword != "" {
20+
password = valuePassword
21+
}
22+
return
23+
}
24+
25+
func createPool() *redis.Pool {
26+
host,_ := getConnectionDetails()
1727
cpool := &redis.Pool{
1828
MaxIdle: 3,
1929
IdleTimeout: 240 * time.Second,
@@ -22,25 +32,41 @@ func createPool() *redis.Pool {
2232
return cpool
2333
}
2434

25-
func createTestClient() *Client {
26-
value, exists := os.LookupEnv("REDISAI_TEST_HOST")
27-
host := "redis://localhost:6379"
35+
func getTLSdetails() (tlsready bool, tls_cert string, tls_key string, tls_cacert string) {
36+
tlsready = false
37+
value, exists := os.LookupEnv("TLS_CERT")
2838
if exists && value != "" {
29-
host = value
39+
tls_cert = value
40+
} else {
41+
return
42+
}
43+
value, exists = os.LookupEnv("TLS_KEY")
44+
if exists && value != "" {
45+
tls_key = value
46+
} else {
47+
return
3048
}
49+
value, exists = os.LookupEnv("TLS_CACERT")
50+
if exists && value != "" {
51+
tls_cacert = value
52+
} else {
53+
return
54+
}
55+
tlsready = true
56+
return
57+
}
58+
59+
func createTestClient() *Client {
60+
host,_ := getConnectionDetails()
3161
return Connect(host, nil)
3262
}
3363

3464
func TestConnect(t *testing.T) {
35-
value, exists := os.LookupEnv("REDISAI_TEST_HOST")
36-
urlTest1 := "redis://localhost:6379"
37-
if exists && value != "" {
38-
urlTest1 = value
39-
}
65+
host,_ := getConnectionDetails()
4066
cpool1 := &redis.Pool{
4167
MaxIdle: 3,
4268
IdleTimeout: 240 * time.Second,
43-
Dial: func() (redis.Conn, error) { return redis.DialURL(urlTest1) },
69+
Dial: func() (redis.Conn, error) { return redis.DialURL(host) },
4470
}
4571

4672
type args struct {
@@ -57,7 +83,7 @@ func TestConnect(t *testing.T) {
5783
pool *redis.Pool
5884
comparePool bool
5985
}{
60-
{"test:Connect:WithPool:1", args{urlTest1, nil, false, 0, 0, nil}, cpool1, false},
86+
{"test:Connect:WithPool:1", args{host, nil, false, 0, 0, nil}, cpool1, false},
6187
}
6288
for _, tt := range tests {
6389
t.Run(tt.name, func(t *testing.T) {
@@ -205,7 +231,7 @@ func TestClient_Receive(t *testing.T) {
205231

206232
func TestClient_DisablePipeline(t *testing.T) {
207233
// Create a client.
208-
client := Connect("redis://localhost:6379", nil)
234+
client := createTestClient()
209235

210236
// Enable pipeline of commands on the client, autoFlushing at 3 commands
211237
client.Pipeline(3)

0 commit comments

Comments
 (0)