-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
140 lines (117 loc) · 3.49 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"context"
"flag"
"fmt"
"log"
"net/http"
"os"
"path"
"strings"
"time"
"cloud.google.com/go/compute/metadata"
redis "cloud.google.com/go/redis/apiv1beta1"
redispb "google.golang.org/genproto/googleapis/cloud/redis/v1beta1"
)
var (
err error
)
// getInstanceProjectID fetches the project id from instance metadata
func getInstanceProjectID(client *metadata.Client) (string, error) {
projectID, err := client.ProjectID()
if err != nil {
return "", err
}
return projectID, nil
}
// getInstanceRegion gets the region for the current instance from metadata
func getInstanceRegion(client *metadata.Client) (string, error) {
zone, err := client.Zone()
if err != nil {
return "", err
}
// get the current region by dropping the ending letter from the zone
zoneArr := strings.Split(zone, "-")
region := strings.Join(zoneArr[:len(zoneArr)-1], "-")
return region, nil
}
// redisInstancePath generates the gcp style resource path for the redis instance
func redisInstancePath(project string, region string, redisName string) string {
return fmt.Sprintf("projects/%s/locations/%s/instances/%s", project, region, redisName)
}
// getRedisInstanceDetails fetches configuration information for the redis instance
func getRedisInstanceDetails(ctx context.Context, client *redis.CloudRedisClient, path string) (*redispb.Instance, error) {
// fetch redis instance details using the instance path
req := &redispb.GetInstanceRequest{Name: path}
resp, err := client.GetInstance(ctx, req)
if err != nil {
return nil, err
}
return resp, nil
}
// writeCAFile creates a crt file from list of certificates on a redis instance
func writeCAFile(certs []*redispb.TlsCertificate, file *os.File) error {
for _, cert := range certs {
log.Printf(
"writting ca cert %s to %s expiring on %s",
cert.Sha1Fingerprint,
file.Name(),
time.Unix(cert.ExpireTime.Seconds, int64(cert.ExpireTime.Nanos)),
)
_, err := file.WriteString(cert.Cert)
if err != nil {
return err
}
}
return nil
}
func main() {
// get cli parameters
cliCAFile := flag.String("caFile", "/certs/redis_ca.crt", "File to write redis CA certificates to.")
cliRedisInstanceName := flag.String("redisInstance", "redis-test-01", "Redis instance name.")
cliProjectID := flag.String("project", "metadata", "GCP project name of redis instance.")
cliRegion := flag.String("region", "metadata", "GCP region of redis instance.")
flag.Parse()
// create client for instance metadata
cm := metadata.NewClient(&http.Client{})
// use metadata for project name if not set on cli
projectID := *cliProjectID
if projectID == "metadata" {
projectID, err = getInstanceProjectID(cm)
if err != nil {
log.Fatalln(err)
}
}
// use metadata for region if not set on cli
region := *cliRegion
if region == "metadata" {
region, err = getInstanceRegion(cm)
if err != nil {
log.Fatalln(err)
}
}
// get the redis instance path in the gcp project
resourcePath := redisInstancePath(projectID, region, *cliRedisInstanceName)
// create gcp redis client
ctx := context.Background()
cr, err := redis.NewCloudRedisClient(ctx)
if err != nil {
log.Fatalln(err)
}
defer cr.Close()
// fetch info of the redis instance
resp, err := getRedisInstanceDetails(ctx, cr, resourcePath)
if err != nil {
log.Fatalln(err)
}
// append redis CA to file
f, err := os.Create(path.Clean(*cliCAFile))
if err != nil {
log.Fatalln(err.Error())
}
defer f.Close()
err = writeCAFile(resp.ServerCaCerts, f)
if err != nil {
log.Fatalln(err)
}
}