server_inspection.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /*
  15. Copyright 2019 The Kubernetes Authors.
  16. Licensed under the Apache License, Version 2.0 (the "License");
  17. you may not use this file except in compliance with the License.
  18. You may obtain a copy of the License at
  19. http://www.apache.org/licenses/LICENSE-2.0
  20. Unless required by applicable law or agreed to in writing, software
  21. distributed under the License is distributed on an "AS IS" BASIS,
  22. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  23. See the License for the specific language governing permissions and
  24. limitations under the License.
  25. */
  26. package cert
  27. import (
  28. "crypto/tls"
  29. "crypto/x509"
  30. "fmt"
  31. "net/url"
  32. "strings"
  33. )
  34. // GetClientCANames gets the CA names for client certs that a server accepts. This is useful when inspecting the
  35. // state of particular servers. apiHost is "host:port"
  36. func GetClientCANames(apiHost string) ([]string, error) {
  37. // when we run this the second time, we know which one we are expecting
  38. acceptableCAs := []string{}
  39. tlsConfig := &tls.Config{
  40. InsecureSkipVerify: true, // this is insecure to always get to the GetClientCertificate
  41. GetClientCertificate: func(hello *tls.CertificateRequestInfo) (*tls.Certificate, error) {
  42. acceptableCAs = []string{}
  43. for _, curr := range hello.AcceptableCAs {
  44. acceptableCAs = append(acceptableCAs, string(curr))
  45. }
  46. return &tls.Certificate{}, nil
  47. },
  48. }
  49. conn, err := tls.Dial("tcp", apiHost, tlsConfig)
  50. if err != nil {
  51. return nil, err
  52. }
  53. if err := conn.Close(); err != nil {
  54. return nil, err
  55. }
  56. return acceptableCAs, nil
  57. }
  58. // GetClientCANamesForURL is GetClientCANames against a URL string like we use in kubeconfigs
  59. func GetClientCANamesForURL(kubeConfigURL string) ([]string, error) {
  60. apiserverURL, err := url.Parse(kubeConfigURL)
  61. if err != nil {
  62. return nil, err
  63. }
  64. return GetClientCANames(apiserverURL.Host)
  65. }
  66. // GetServingCertificates returns the x509 certs used by a server as certificates and pem encoded bytes.
  67. // The serverName is optional for specifying a different name to get SNI certificates. apiHost is "host:port"
  68. func GetServingCertificates(apiHost, serverName string) ([]*x509.Certificate, [][]byte, error) {
  69. tlsConfig := &tls.Config{
  70. InsecureSkipVerify: true, // this is insecure so that we always get connected
  71. }
  72. // if a name is specified for SNI, set it.
  73. if len(serverName) > 0 {
  74. tlsConfig.ServerName = serverName
  75. }
  76. conn, err := tls.Dial("tcp", apiHost, tlsConfig)
  77. if err != nil {
  78. return nil, nil, err
  79. }
  80. if err = conn.Close(); err != nil {
  81. return nil, nil, fmt.Errorf("failed to close connection : %v", err)
  82. }
  83. peerCerts := conn.ConnectionState().PeerCertificates
  84. peerCertBytes := [][]byte{}
  85. for _, a := range peerCerts {
  86. actualCert, err := EncodeCertificates(a)
  87. if err != nil {
  88. return nil, nil, err
  89. }
  90. peerCertBytes = append(peerCertBytes, []byte(strings.TrimSpace(string(actualCert))))
  91. }
  92. return peerCerts, peerCertBytes, err
  93. }
  94. // GetServingCertificatesForURL is GetServingCertificates against a URL string like we use in kubeconfigs
  95. func GetServingCertificatesForURL(kubeConfigURL, serverName string) ([]*x509.Certificate, [][]byte, error) {
  96. apiserverURL, err := url.Parse(kubeConfigURL)
  97. if err != nil {
  98. return nil, nil, err
  99. }
  100. return GetServingCertificates(apiserverURL.Host, serverName)
  101. }