Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
5dc31d35
Commit
5dc31d35
authored
Oct 19, 2016
by
Dr. Stefan Schimanski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add --tls-sni-cert-key to the apiserver for SNI support
parent
d0b3981f
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
350 additions
and
34 deletions
+350
-34
server.go
cmd/kubelet/app/server.go
+11
-1
known-flags.txt
hack/verify-flags/known-flags.txt
+1
-0
config.go
pkg/genericapiserver/config.go
+52
-10
genericapiserver.go
pkg/genericapiserver/genericapiserver.go
+1
-1
server_run_options.go
pkg/genericapiserver/options/server_run_options.go
+12
-2
serve.go
pkg/genericapiserver/serve.go
+14
-1
serve_test.go
pkg/genericapiserver/serve_test.go
+0
-0
cert.go
pkg/util/cert/cert.go
+8
-19
namedcertkey_flag.go
pkg/util/config/namedcertkey_flag.go
+113
-0
namedcertkey_flag_test.go
pkg/util/config/namedcertkey_flag_test.go
+138
-0
No files found.
cmd/kubelet/app/server.go
View file @
5dc31d35
...
...
@@ -502,9 +502,19 @@ func InitializeTLS(kc *componentconfig.KubeletConfiguration) (*server.TLSOptions
kc
.
TLSCertFile
=
path
.
Join
(
kc
.
CertDirectory
,
"kubelet.crt"
)
kc
.
TLSPrivateKeyFile
=
path
.
Join
(
kc
.
CertDirectory
,
"kubelet.key"
)
if
!
certutil
.
CanReadCertOrKey
(
kc
.
TLSCertFile
,
kc
.
TLSPrivateKeyFile
)
{
if
err
:=
certutil
.
GenerateSelfSignedCert
(
nodeutil
.
GetHostname
(
kc
.
HostnameOverride
),
kc
.
TLSCertFile
,
kc
.
TLSPrivateKeyFile
,
nil
,
nil
);
err
!=
nil
{
cert
,
key
,
err
:=
certutil
.
GenerateSelfSignedCertKey
(
nodeutil
.
GetHostname
(
kc
.
HostnameOverride
),
nil
,
nil
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"unable to generate self signed cert: %v"
,
err
)
}
if
err
:=
certutil
.
WriteCert
(
kc
.
TLSCertFile
,
cert
);
err
!=
nil
{
return
nil
,
err
}
if
err
:=
certutil
.
WriteKey
(
kc
.
TLSPrivateKeyFile
,
key
);
err
!=
nil
{
return
nil
,
err
}
glog
.
V
(
4
)
.
Infof
(
"Using self-signed cert (%s, %s)"
,
kc
.
TLSCertFile
,
kc
.
TLSPrivateKeyFile
)
}
}
...
...
hack/verify-flags/known-flags.txt
View file @
5dc31d35
...
...
@@ -555,6 +555,7 @@ tls-ca-file
tls-cert-file
tls-private-key-file
to-version
tls-sni-cert-key
token-auth-file
ttl-keys-prefix
ttl-secs
...
...
pkg/genericapiserver/config.go
View file @
5dc31d35
...
...
@@ -110,7 +110,7 @@ type Config struct {
// same value for this field. (Numbers > 1 currently untested.)
MasterCount
int
SecureServingInfo
*
ServingInfo
SecureServingInfo
*
Se
cureSe
rvingInfo
InsecureServingInfo
*
ServingInfo
// The port on PublicAddress where a read-write server will be installed.
...
...
@@ -177,17 +177,36 @@ type Config struct {
type
ServingInfo
struct
{
// BindAddress is the ip:port to serve on
BindAddress
string
}
type
SecureServingInfo
struct
{
ServingInfo
// ServerCert is the TLS cert info for serving secure traffic
ServerCert
CertInfo
ServerCert
GeneratableKeyCert
// SNICerts are named CertKeys for serving secure traffic with SNI support.
SNICerts
[]
NamedCertKey
// ClientCA is the certificate bundle for all the signers that you'll recognize for incoming client certificates
ClientCA
string
}
type
Cert
Info
struct
{
type
Cert
Key
struct
{
// CertFile is a file containing a PEM-encoded certificate
CertFile
string
// KeyFile is a file containing a PEM-encoded private key for the certificate specified by CertFile
KeyFile
string
}
type
NamedCertKey
struct
{
CertKey
// Names is a list of domain patterns: fully qualified domain names, possibly prefixed with
// wildcard segments.
Names
[]
string
}
type
GeneratableKeyCert
struct
{
CertKey
// Generate indicates that the cert/key pair should be generated if its not present.
Generate
bool
}
...
...
@@ -248,12 +267,17 @@ func (c *Config) ApplyOptions(options *options.ServerRunOptions) *Config {
}
if
options
.
SecurePort
>
0
{
secureServingInfo
:=
&
ServingInfo
{
BindAddress
:
net
.
JoinHostPort
(
options
.
BindAddress
.
String
(),
strconv
.
Itoa
(
options
.
SecurePort
)),
ServerCert
:
CertInfo
{
CertFile
:
options
.
TLSCertFile
,
KeyFile
:
options
.
TLSPrivateKeyFile
,
secureServingInfo
:=
&
SecureServingInfo
{
ServingInfo
:
ServingInfo
{
BindAddress
:
net
.
JoinHostPort
(
options
.
BindAddress
.
String
(),
strconv
.
Itoa
(
options
.
SecurePort
)),
},
ServerCert
:
GeneratableKeyCert
{
CertKey
:
CertKey
{
CertFile
:
options
.
TLSCertFile
,
KeyFile
:
options
.
TLSPrivateKeyFile
,
},
},
SNICerts
:
[]
NamedCertKey
{},
ClientCA
:
options
.
ClientCAFile
,
}
if
options
.
TLSCertFile
==
""
&&
options
.
TLSPrivateKeyFile
==
""
{
...
...
@@ -262,6 +286,17 @@ func (c *Config) ApplyOptions(options *options.ServerRunOptions) *Config {
secureServingInfo
.
ServerCert
.
KeyFile
=
path
.
Join
(
options
.
CertDirectory
,
"apiserver.key"
)
}
secureServingInfo
.
SNICerts
=
nil
for
_
,
nkc
:=
range
options
.
SNICertKeys
{
secureServingInfo
.
SNICerts
=
append
(
secureServingInfo
.
SNICerts
,
NamedCertKey
{
CertKey
:
CertKey
{
KeyFile
:
nkc
.
KeyFile
,
CertFile
:
nkc
.
CertFile
,
},
Names
:
nkc
.
Names
,
})
}
c
.
SecureServingInfo
=
secureServingInfo
c
.
ReadWritePort
=
options
.
SecurePort
}
...
...
@@ -434,9 +469,16 @@ func (c completedConfig) MaybeGenerateServingCerts() error {
alternateIPs
:=
[]
net
.
IP
{
c
.
ServiceReadWriteIP
}
alternateDNS
:=
[]
string
{
"kubernetes.default.svc"
,
"kubernetes.default"
,
"kubernetes"
,
"localhost"
}
if
err
:=
certutil
.
GenerateSelfSignedCert
(
c
.
PublicAddress
.
String
(),
c
.
SecureServingInfo
.
ServerCert
.
CertFile
,
c
.
SecureServingInfo
.
ServerCert
.
KeyFile
,
alternateIPs
,
alternateDNS
);
err
!=
nil
{
return
fmt
.
Errorf
(
"
U
nable to generate self signed cert: %v"
,
err
)
if
cert
,
key
,
err
:=
certutil
.
GenerateSelfSignedCertKey
(
c
.
PublicAddress
.
String
()
,
alternateIPs
,
alternateDNS
);
err
!=
nil
{
return
fmt
.
Errorf
(
"
u
nable to generate self signed cert: %v"
,
err
)
}
else
{
if
err
:=
certutil
.
WriteCert
(
c
.
SecureServingInfo
.
ServerCert
.
CertFile
,
cert
);
err
!=
nil
{
return
err
}
if
err
:=
certutil
.
WriteKey
(
c
.
SecureServingInfo
.
ServerCert
.
KeyFile
,
key
);
err
!=
nil
{
return
err
}
glog
.
Infof
(
"Generated self-signed cert (%s, %s)"
,
c
.
SecureServingInfo
.
ServerCert
.
CertFile
,
c
.
SecureServingInfo
.
ServerCert
.
KeyFile
)
}
}
...
...
pkg/genericapiserver/genericapiserver.go
View file @
5dc31d35
...
...
@@ -109,7 +109,7 @@ type GenericAPIServer struct {
// The registered APIs
HandlerContainer
*
genericmux
.
APIContainer
SecureServingInfo
*
ServingInfo
SecureServingInfo
*
Se
cureSe
rvingInfo
InsecureServingInfo
*
ServingInfo
// numerical ports, set after listening
...
...
pkg/genericapiserver/options/server_run_options.go
View file @
5dc31d35
...
...
@@ -118,6 +118,7 @@ type ServerRunOptions struct {
TLSCAFile
string
TLSCertFile
string
TLSPrivateKeyFile
string
SNICertKeys
[]
config
.
NamedCertKey
TokenAuthFile
string
EnableAnyToken
bool
WatchCacheSizes
[]
string
...
...
@@ -488,13 +489,22 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
"Controllers. This must be a valid PEM-encoded CA bundle."
)
fs
.
StringVar
(
&
s
.
TLSCertFile
,
"tls-cert-file"
,
s
.
TLSCertFile
,
""
+
"File containing x509 Certificate for HTTPS. (CA cert, if any, concatenated "
+
"File containing
the default
x509 Certificate for HTTPS. (CA cert, if any, concatenated "
+
"after server cert). If HTTPS serving is enabled, and --tls-cert-file and "
+
"--tls-private-key-file are not provided, a self-signed certificate and key "
+
"are generated for the public address and saved to /var/run/kubernetes."
)
fs
.
StringVar
(
&
s
.
TLSPrivateKeyFile
,
"tls-private-key-file"
,
s
.
TLSPrivateKeyFile
,
"File containing x509 private key matching --tls-cert-file."
)
"File containing the default x509 private key matching --tls-cert-file."
)
fs
.
Var
(
config
.
NewNamedCertKeyArray
(
&
s
.
SNICertKeys
),
"tls-sni-cert-key"
,
""
+
"A pair of x509 certificate and private key file paths, optionally suffixed with a list of "
+
"domain patterns which are fully qualified domain names, possibly with prefixed wildcard "
+
"segments. If no domain patterns are provided, the names of the certificate are "
+
"extracted. Non-wildcard matches trump over wildcard matches, explicit domain patterns "
+
"trump over extracted names. For multiple key/certificate pairs, use the "
+
"--tls-sni-cert-key multiple times. "
+
"Examples:
\"
example.key,example.crt
\"
or
\"
*.foo.com,foo.com:foo.key,foo.crt
\"
."
)
fs
.
StringVar
(
&
s
.
TokenAuthFile
,
"token-auth-file"
,
s
.
TokenAuthFile
,
""
+
"If set, the file that will be used to secure the secure port of the API server "
+
...
...
pkg/genericapiserver/serve.go
View file @
5dc31d35
...
...
@@ -40,11 +40,17 @@ const (
// be loaded or the initial listen call fails. The actual server loop (stoppable by closing
// stopCh) runs in a go routine, i.e. serveSecurely does not block.
func
(
s
*
GenericAPIServer
)
serveSecurely
(
stopCh
<-
chan
struct
{})
error
{
namedCerts
,
err
:=
getNamedCertificateMap
(
s
.
SecureServingInfo
.
SNICerts
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"unable to load SNI certificates: %v"
,
err
)
}
secureServer
:=
&
http
.
Server
{
Addr
:
s
.
SecureServingInfo
.
BindAddress
,
Handler
:
s
.
Handler
,
MaxHeaderBytes
:
1
<<
20
,
TLSConfig
:
&
tls
.
Config
{
NameToCertificate
:
namedCerts
,
// Can't use SSLv3 because of POODLE and BEAST
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
// Can't use TLSv1.1 because of RC4 cipher usage
...
...
@@ -54,7 +60,6 @@ func (s *GenericAPIServer) serveSecurely(stopCh <-chan struct{}) error {
},
}
var
err
error
if
len
(
s
.
SecureServingInfo
.
ServerCert
.
CertFile
)
!=
0
||
len
(
s
.
SecureServingInfo
.
ServerCert
.
KeyFile
)
!=
0
{
secureServer
.
TLSConfig
.
Certificates
=
make
([]
tls
.
Certificate
,
1
)
secureServer
.
TLSConfig
.
Certificates
[
0
],
err
=
tls
.
LoadX509KeyPair
(
s
.
SecureServingInfo
.
ServerCert
.
CertFile
,
s
.
SecureServingInfo
.
ServerCert
.
KeyFile
)
...
...
@@ -63,6 +68,14 @@ func (s *GenericAPIServer) serveSecurely(stopCh <-chan struct{}) error {
}
}
// append all named certs. Otherwise, the go tls stack will think no SNI processing
// is necessary because there is only one cert anyway.
// Moreover, if ServerCert.CertFile/ServerCert.KeyFile are not set, the first SNI
// cert will become the default cert. That's what we expect anyway.
for
_
,
c
:=
range
namedCerts
{
secureServer
.
TLSConfig
.
Certificates
=
append
(
secureServer
.
TLSConfig
.
Certificates
,
*
c
)
}
if
len
(
s
.
SecureServingInfo
.
ClientCA
)
>
0
{
clientCAs
,
err
:=
certutil
.
NewPool
(
s
.
SecureServingInfo
.
ClientCA
)
if
err
!=
nil
{
...
...
pkg/genericapiserver/serve_test.go
0 → 100644
View file @
5dc31d35
This diff is collapsed.
Click to expand it.
pkg/util/cert/cert.go
View file @
5dc31d35
...
...
@@ -126,22 +126,19 @@ func MakeEllipticPrivateKeyPEM() ([]byte, error) {
return
pem
.
EncodeToMemory
(
privateKeyPemBlock
),
nil
}
// GenerateSelfSignedCert creates a self-signed certificate and key for the given host.
// GenerateSelfSignedCert
Key
creates a self-signed certificate and key for the given host.
// Host may be an IP or a DNS name
// You may also specify additional subject alt names (either ip or dns names) for the certificate
// The certificate will be created with file mode 0644. The key will be created with file mode 0600.
// If the certificate or key files already exist, they will be overwritten.
// Any parent directories of the certPath or keyPath will be created as needed with file mode 0755.
func
GenerateSelfSignedCert
(
host
,
certPath
,
keyPath
string
,
alternateIPs
[]
net
.
IP
,
alternateDNS
[]
string
)
error
{
func
GenerateSelfSignedCertKey
(
host
string
,
alternateIPs
[]
net
.
IP
,
alternateDNS
[]
string
)
([]
byte
,
[]
byte
,
error
)
{
priv
,
err
:=
rsa
.
GenerateKey
(
cryptorand
.
Reader
,
2048
)
if
err
!=
nil
{
return
err
return
nil
,
nil
,
err
}
template
:=
x509
.
Certificate
{
SerialNumber
:
big
.
NewInt
(
1
),
Subject
:
pkix
.
Name
{
CommonName
:
fmt
.
Sprintf
(
"%s@%d"
,
host
,
time
.
Now
()
.
Unix
())
,
CommonName
:
host
,
},
NotBefore
:
time
.
Now
(),
NotAfter
:
time
.
Now
()
.
Add
(
time
.
Hour
*
24
*
365
),
...
...
@@ -163,30 +160,22 @@ func GenerateSelfSignedCert(host, certPath, keyPath string, alternateIPs []net.I
derBytes
,
err
:=
x509
.
CreateCertificate
(
cryptorand
.
Reader
,
&
template
,
&
template
,
&
priv
.
PublicKey
,
priv
)
if
err
!=
nil
{
return
err
return
nil
,
nil
,
err
}
// Generate cert
certBuffer
:=
bytes
.
Buffer
{}
if
err
:=
pem
.
Encode
(
&
certBuffer
,
&
pem
.
Block
{
Type
:
"CERTIFICATE"
,
Bytes
:
derBytes
});
err
!=
nil
{
return
err
return
nil
,
nil
,
err
}
// Generate key
keyBuffer
:=
bytes
.
Buffer
{}
if
err
:=
pem
.
Encode
(
&
keyBuffer
,
&
pem
.
Block
{
Type
:
"RSA PRIVATE KEY"
,
Bytes
:
x509
.
MarshalPKCS1PrivateKey
(
priv
)});
err
!=
nil
{
return
err
return
nil
,
nil
,
err
}
if
err
:=
WriteCert
(
certPath
,
certBuffer
.
Bytes
());
err
!=
nil
{
return
err
}
if
err
:=
WriteKey
(
keyPath
,
keyBuffer
.
Bytes
());
err
!=
nil
{
return
err
}
return
nil
return
certBuffer
.
Bytes
(),
keyBuffer
.
Bytes
(),
nil
}
// FormatBytesCert receives byte array certificate and formats in human-readable format
...
...
pkg/util/config/namedcertkey_flag.go
0 → 100644
View file @
5dc31d35
/*
Copyright 2016 The Kubernetes Authors.
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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
config
import
(
"errors"
"flag"
"strings"
)
// NamedCertKey is a flag value parsing "certfile,keyfile" and "certfile,keyfile:name,name,name".
type
NamedCertKey
struct
{
Names
[]
string
CertFile
,
KeyFile
string
}
var
_
flag
.
Value
=
&
NamedCertKey
{}
func
(
nkc
*
NamedCertKey
)
String
()
string
{
s
:=
nkc
.
CertFile
+
","
+
nkc
.
KeyFile
if
len
(
nkc
.
Names
)
>
0
{
s
=
s
+
":"
+
strings
.
Join
(
nkc
.
Names
,
","
)
}
return
s
}
func
(
nkc
*
NamedCertKey
)
Set
(
value
string
)
error
{
cs
:=
strings
.
SplitN
(
value
,
":"
,
2
)
var
keycert
string
if
len
(
cs
)
==
2
{
var
names
string
keycert
,
names
=
strings
.
TrimSpace
(
cs
[
0
]),
strings
.
TrimSpace
(
cs
[
1
])
if
names
==
""
{
return
errors
.
New
(
"empty names list is not allowed"
)
}
nkc
.
Names
=
nil
for
_
,
name
:=
range
strings
.
Split
(
names
,
","
)
{
nkc
.
Names
=
append
(
nkc
.
Names
,
strings
.
TrimSpace
(
name
))
}
}
else
{
nkc
.
Names
=
nil
keycert
=
strings
.
TrimSpace
(
cs
[
0
])
}
cs
=
strings
.
Split
(
keycert
,
","
)
if
len
(
cs
)
!=
2
{
return
errors
.
New
(
"expected comma separated certificate and key file paths"
)
}
nkc
.
CertFile
=
strings
.
TrimSpace
(
cs
[
0
])
nkc
.
KeyFile
=
strings
.
TrimSpace
(
cs
[
1
])
return
nil
}
func
(
*
NamedCertKey
)
Type
()
string
{
return
"namedCertKey"
}
// NamedCertKeyArray is a flag value parsing NamedCertKeys, each passed with its own
// flag instance (in contrast to comma separated slices).
type
NamedCertKeyArray
struct
{
value
*
[]
NamedCertKey
changed
bool
}
var
_
flag
.
Value
=
&
NamedCertKey
{}
// NewNamedKeyCertArray creates a new NamedCertKeyArray with the internal value
// pointing to p.
func
NewNamedCertKeyArray
(
p
*
[]
NamedCertKey
)
*
NamedCertKeyArray
{
return
&
NamedCertKeyArray
{
value
:
p
,
}
}
func
(
a
*
NamedCertKeyArray
)
Set
(
val
string
)
error
{
nkc
:=
NamedCertKey
{}
err
:=
nkc
.
Set
(
val
)
if
err
!=
nil
{
return
err
}
if
!
a
.
changed
{
*
a
.
value
=
[]
NamedCertKey
{
nkc
}
a
.
changed
=
true
}
else
{
*
a
.
value
=
append
(
*
a
.
value
,
nkc
)
}
return
nil
}
func
(
a
*
NamedCertKeyArray
)
Type
()
string
{
return
"namedCertKey"
}
func
(
a
*
NamedCertKeyArray
)
String
()
string
{
nkcs
:=
make
([]
string
,
0
,
len
(
*
a
.
value
))
for
i
:=
range
*
a
.
value
{
nkcs
=
append
(
nkcs
,
(
*
a
.
value
)[
i
]
.
String
())
}
return
"["
+
strings
.
Join
(
nkcs
,
";"
)
+
"]"
}
pkg/util/config/namedcertkey_flag_test.go
0 → 100644
View file @
5dc31d35
/*
Copyright 2016 The Kubernetes Authors.
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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
config
import
(
"fmt"
"github.com/spf13/pflag"
"reflect"
"strings"
"testing"
)
func
TestNamedCertKeyArrayFlag
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
args
[]
string
def
[]
NamedCertKey
expected
[]
NamedCertKey
parseError
string
}{
{
args
:
[]
string
{},
expected
:
nil
,
},
{
args
:
[]
string
{
"foo.crt,foo.key"
},
expected
:
[]
NamedCertKey
{{
KeyFile
:
"foo.key"
,
CertFile
:
"foo.crt"
,
}},
},
{
args
:
[]
string
{
" foo.crt , foo.key "
},
expected
:
[]
NamedCertKey
{{
KeyFile
:
"foo.key"
,
CertFile
:
"foo.crt"
,
}},
},
{
args
:
[]
string
{
"foo.crt,foo.key:abc"
},
expected
:
[]
NamedCertKey
{{
KeyFile
:
"foo.key"
,
CertFile
:
"foo.crt"
,
Names
:
[]
string
{
"abc"
},
}},
},
{
args
:
[]
string
{
"foo.crt,foo.key: abc "
},
expected
:
[]
NamedCertKey
{{
KeyFile
:
"foo.key"
,
CertFile
:
"foo.crt"
,
Names
:
[]
string
{
"abc"
},
}},
},
{
args
:
[]
string
{
"foo.crt,foo.key:"
},
parseError
:
"empty names list is not allowed"
,
},
{
args
:
[]
string
{
""
},
parseError
:
"expected comma separated certificate and key file paths"
,
},
{
args
:
[]
string
{
" "
},
parseError
:
"expected comma separated certificate and key file paths"
,
},
{
args
:
[]
string
{
"a,b,c"
},
parseError
:
"expected comma separated certificate and key file paths"
,
},
{
args
:
[]
string
{
"foo.crt,foo.key:abc,def,ghi"
},
expected
:
[]
NamedCertKey
{{
KeyFile
:
"foo.key"
,
CertFile
:
"foo.crt"
,
Names
:
[]
string
{
"abc"
,
"def"
,
"ghi"
},
}},
},
{
args
:
[]
string
{
"foo.crt,foo.key:*.*.*"
},
expected
:
[]
NamedCertKey
{{
KeyFile
:
"foo.key"
,
CertFile
:
"foo.crt"
,
Names
:
[]
string
{
"*.*.*"
},
}},
},
{
args
:
[]
string
{
"foo.crt,foo.key"
,
"bar.crt,bar.key"
},
expected
:
[]
NamedCertKey
{{
KeyFile
:
"foo.key"
,
CertFile
:
"foo.crt"
,
},
{
KeyFile
:
"bar.key"
,
CertFile
:
"bar.crt"
,
}},
},
}
for
i
,
test
:=
range
tests
{
fs
:=
pflag
.
NewFlagSet
(
"testNamedCertKeyArray"
,
pflag
.
ContinueOnError
)
var
nkcs
[]
NamedCertKey
for
_
,
d
:=
range
test
.
def
{
nkcs
=
append
(
nkcs
,
d
)
}
fs
.
Var
(
NewNamedCertKeyArray
(
&
nkcs
),
"tls-sni-cert-key"
,
"usage"
)
args
:=
[]
string
{}
for
_
,
a
:=
range
test
.
args
{
args
=
append
(
args
,
fmt
.
Sprintf
(
"--tls-sni-cert-key=%s"
,
a
))
}
err
:=
fs
.
Parse
(
args
)
if
test
.
parseError
!=
""
{
if
err
==
nil
{
t
.
Errorf
(
"%d: expected error %q, got nil"
,
i
,
test
.
parseError
)
}
else
if
!
strings
.
Contains
(
err
.
Error
(),
test
.
parseError
)
{
t
.
Errorf
(
"%d: expected error %q, got %q"
,
i
,
test
.
parseError
,
err
)
}
}
else
if
err
!=
nil
{
t
.
Errorf
(
"%d: expected nil error, got %v"
,
i
,
err
)
}
if
!
reflect
.
DeepEqual
(
nkcs
,
test
.
expected
)
{
t
.
Errorf
(
"%d: expected %+v, got %+v"
,
i
,
test
.
expected
,
nkcs
)
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment