/
clientencryptionoptions.go
150 lines (135 loc) · 5.38 KB
/
clientencryptionoptions.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
141
142
143
144
145
146
147
148
149
150
// Copyright (C) MongoDB, Inc. 2017-present.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
package options
import (
"crypto/tls"
"fmt"
"net/http"
"go.mongodb.org/mongo-driver/internal/httputil"
)
// ClientEncryptionOptions represents all possible options used to configure a ClientEncryption instance.
type ClientEncryptionOptions struct {
KeyVaultNamespace string
KmsProviders map[string]map[string]interface{}
TLSConfig map[string]*tls.Config
HTTPClient *http.Client
}
// ClientEncryption creates a new ClientEncryptionOptions instance.
func ClientEncryption() *ClientEncryptionOptions {
return &ClientEncryptionOptions{
HTTPClient: httputil.DefaultHTTPClient,
}
}
// SetKeyVaultNamespace specifies the namespace of the key vault collection. This is required.
func (c *ClientEncryptionOptions) SetKeyVaultNamespace(ns string) *ClientEncryptionOptions {
c.KeyVaultNamespace = ns
return c
}
// SetKmsProviders specifies options for KMS providers. This is required.
func (c *ClientEncryptionOptions) SetKmsProviders(providers map[string]map[string]interface{}) *ClientEncryptionOptions {
c.KmsProviders = providers
return c
}
// SetTLSConfig specifies tls.Config instances for each KMS provider to use to configure TLS on all connections created
// to the KMS provider.
//
// This should only be used to set custom TLS configurations. By default, the connection will use an empty tls.Config{} with MinVersion set to tls.VersionTLS12.
func (c *ClientEncryptionOptions) SetTLSConfig(tlsOpts map[string]*tls.Config) *ClientEncryptionOptions {
tlsConfigs := make(map[string]*tls.Config)
for provider, config := range tlsOpts {
// use TLS min version 1.2 to enforce more secure hash algorithms and advanced cipher suites
if config.MinVersion == 0 {
config.MinVersion = tls.VersionTLS12
}
tlsConfigs[provider] = config
}
c.TLSConfig = tlsConfigs
return c
}
// BuildTLSConfig specifies tls.Config options for each KMS provider to use to configure TLS on all connections created
// to the KMS provider. The input map should contain a mapping from each KMS provider to a document containing the necessary
// options, as follows:
//
// {
// "kmip": {
// "tlsCertificateKeyFile": "foo.pem",
// "tlsCAFile": "fooCA.pem"
// }
// }
//
// Currently, the following TLS options are supported:
//
// 1. "tlsCertificateKeyFile" (or "sslClientCertificateKeyFile"): The "tlsCertificateKeyFile" option specifies a path to
// the client certificate and private key, which must be concatenated into one file.
//
// 2. "tlsCertificateKeyFilePassword" (or "sslClientCertificateKeyPassword"): Specify the password to decrypt the client
// private key file (e.g. "tlsCertificateKeyFilePassword=password").
//
// 3. "tlsCaFile" (or "sslCertificateAuthorityFile"): Specify the path to a single or bundle of certificate authorities
// to be considered trusted when making a TLS connection (e.g. "tlsCaFile=/path/to/caFile").
//
// This should only be used to set custom TLS options. By default, the connection will use an empty tls.Config{} with MinVersion set to tls.VersionTLS12.
func BuildTLSConfig(tlsOpts map[string]interface{}) (*tls.Config, error) {
// use TLS min version 1.2 to enforce more secure hash algorithms and advanced cipher suites
cfg := &tls.Config{MinVersion: tls.VersionTLS12}
for name := range tlsOpts {
var err error
switch name {
case "tlsCertificateKeyFile", "sslClientCertificateKeyFile":
clientCertPath, ok := tlsOpts[name].(string)
if !ok {
return nil, fmt.Errorf("expected %q value to be of type string, got %T", name, tlsOpts[name])
}
// apply custom key file password if found, otherwise use empty string
if keyPwd, found := tlsOpts["tlsCertificateKeyFilePassword"].(string); found {
_, err = addClientCertFromConcatenatedFile(cfg, clientCertPath, keyPwd)
} else if keyPwd, found := tlsOpts["sslClientCertificateKeyPassword"].(string); found {
_, err = addClientCertFromConcatenatedFile(cfg, clientCertPath, keyPwd)
} else {
_, err = addClientCertFromConcatenatedFile(cfg, clientCertPath, "")
}
case "tlsCertificateKeyFilePassword", "sslClientCertificateKeyPassword":
continue
case "tlsCAFile", "sslCertificateAuthorityFile":
caPath, ok := tlsOpts[name].(string)
if !ok {
return nil, fmt.Errorf("expected %q value to be of type string, got %T", name, tlsOpts[name])
}
err = addCACertFromFile(cfg, caPath)
default:
return nil, fmt.Errorf("unrecognized TLS option %v", name)
}
if err != nil {
return nil, err
}
}
return cfg, nil
}
// MergeClientEncryptionOptions combines the argued ClientEncryptionOptions in a last-one wins fashion.
//
// Deprecated: Merging options structs will not be supported in Go Driver 2.0. Users should create a
// single options struct instead.
func MergeClientEncryptionOptions(opts ...*ClientEncryptionOptions) *ClientEncryptionOptions {
ceo := ClientEncryption()
for _, opt := range opts {
if opt == nil {
continue
}
if opt.KeyVaultNamespace != "" {
ceo.KeyVaultNamespace = opt.KeyVaultNamespace
}
if opt.KmsProviders != nil {
ceo.KmsProviders = opt.KmsProviders
}
if opt.TLSConfig != nil {
ceo.TLSConfig = opt.TLSConfig
}
if opt.HTTPClient != nil {
ceo.HTTPClient = opt.HTTPClient
}
}
return ceo
}