admission_webhook.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. Copyright 2019 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package utils
  14. import (
  15. "crypto/tls"
  16. "crypto/x509"
  17. "encoding/json"
  18. "fmt"
  19. "io/ioutil"
  20. "net/http"
  21. "net/http/httptest"
  22. "testing"
  23. "k8s.io/api/admission/v1beta1"
  24. )
  25. // NewAdmissionWebhookServer sets up a webhook server with TLS enabled, returns URL and Close function
  26. // for the server
  27. func NewAdmissionWebhookServer(handler http.Handler) (string, func(), error) {
  28. // set up webhook server
  29. roots := x509.NewCertPool()
  30. if !roots.AppendCertsFromPEM(LocalhostCert) {
  31. return "", nil, fmt.Errorf("Failed to append Cert from PEM")
  32. }
  33. cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey)
  34. if err != nil {
  35. return "", nil, fmt.Errorf("Failed to build cert with error: %+v", err)
  36. }
  37. webhookServer := httptest.NewUnstartedServer(handler)
  38. webhookServer.TLS = &tls.Config{
  39. RootCAs: roots,
  40. Certificates: []tls.Certificate{cert},
  41. }
  42. webhookServer.StartTLS()
  43. return webhookServer.URL, webhookServer.Close, nil
  44. }
  45. // AdmissionWebhookHandler creates a HandlerFunc that decodes/encodes AdmissionReview and performs
  46. // given admit function
  47. func AdmissionWebhookHandler(t *testing.T, admit func(*v1beta1.AdmissionReview) error) http.HandlerFunc {
  48. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  49. defer r.Body.Close()
  50. data, err := ioutil.ReadAll(r.Body)
  51. if err != nil {
  52. t.Error(err)
  53. return
  54. }
  55. if contentType := r.Header.Get("Content-Type"); contentType != "application/json" {
  56. t.Errorf("contentType=%s, expect application/json", contentType)
  57. return
  58. }
  59. review := v1beta1.AdmissionReview{}
  60. if err := json.Unmarshal(data, &review); err != nil {
  61. t.Errorf("Fail to deserialize object: %s with error: %v", string(data), err)
  62. http.Error(w, err.Error(), 400)
  63. return
  64. }
  65. if err := admit(&review); err != nil {
  66. t.Errorf("%v", err)
  67. http.Error(w, err.Error(), 400)
  68. return
  69. }
  70. w.Header().Set("Content-Type", "application/json")
  71. if err := json.NewEncoder(w).Encode(review); err != nil {
  72. t.Errorf("Marshal of response failed with error: %v", err)
  73. }
  74. })
  75. }
  76. // LocalhostCert was generated from crypto/tls/generate_cert.go with the following command:
  77. // go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
  78. var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
  79. MIIDGDCCAgCgAwIBAgIQTKCKn99d5HhQVCLln2Q+eTANBgkqhkiG9w0BAQsFADAS
  80. MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
  81. MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
  82. MIIBCgKCAQEA1Z5/aTwqY706M34tn60l8ZHkanWDl8mM1pYf4Q7qg3zA9XqWLX6S
  83. 4rTYDYCb4stEasC72lQnbEWHbthiQE76zubP8WOFHdvGR3mjAvHWz4FxvLOTheZ+
  84. 3iDUrl6Aj9UIsYqzmpBJAoY4+vGGf+xHvuukHrVcFqR9ZuBdZuJ/HbbjUyuNr3X9
  85. erNIr5Ha17gVzf17SNbYgNrX9gbCeEB8Z9Ox7dVuJhLDkpF0T/B5Zld3BjyUVY/T
  86. cukU4dTVp6isbWPvCMRCZCCOpb+qIhxEjJ0n6tnPt8nf9lvDl4SWMl6X1bH+2EFa
  87. a8R06G0QI+XhwPyjXUyCR8QEOZPCR5wyqQIDAQABo2gwZjAOBgNVHQ8BAf8EBAMC
  88. AqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAuBgNVHREE
  89. JzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG
  90. 9w0BAQsFAAOCAQEAThqgJ/AFqaANsOp48lojDZfZBFxJQ3A4zfR/MgggUoQ9cP3V
  91. rxuKAFWQjze1EZc7J9iO1WvH98lOGVNRY/t2VIrVoSsBiALP86Eew9WucP60tbv2
  92. 8/zsBDSfEo9Wl+Q/gwdEh8dgciUKROvCm76EgAwPGicMAgRsxXgwXHhS5e8nnbIE
  93. Ewaqvb5dY++6kh0Oz+adtNT5OqOwXTIRI67WuEe6/B3Z4LNVPQDIj7ZUJGNw8e6L
  94. F4nkUthwlKx4yEJHZBRuFPnO7Z81jNKuwL276+mczRH7piI6z9uyMV/JbEsOIxyL
  95. W6CzB7pZ9Nj1YLpgzc1r6oONHLokMJJIz/IvkQ==
  96. -----END CERTIFICATE-----`)
  97. // LocalhostKey is the private key for LocalhostCert.
  98. var LocalhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
  99. MIIEowIBAAKCAQEA1Z5/aTwqY706M34tn60l8ZHkanWDl8mM1pYf4Q7qg3zA9XqW
  100. LX6S4rTYDYCb4stEasC72lQnbEWHbthiQE76zubP8WOFHdvGR3mjAvHWz4FxvLOT
  101. heZ+3iDUrl6Aj9UIsYqzmpBJAoY4+vGGf+xHvuukHrVcFqR9ZuBdZuJ/HbbjUyuN
  102. r3X9erNIr5Ha17gVzf17SNbYgNrX9gbCeEB8Z9Ox7dVuJhLDkpF0T/B5Zld3BjyU
  103. VY/TcukU4dTVp6isbWPvCMRCZCCOpb+qIhxEjJ0n6tnPt8nf9lvDl4SWMl6X1bH+
  104. 2EFaa8R06G0QI+XhwPyjXUyCR8QEOZPCR5wyqQIDAQABAoIBAFAJmb1pMIy8OpFO
  105. hnOcYWoYepe0vgBiIOXJy9n8R7vKQ1X2f0w+b3SHw6eTd1TLSjAhVIEiJL85cdwD
  106. MRTdQrXA30qXOioMzUa8eWpCCHUpD99e/TgfO4uoi2dluw+pBx/WUyLnSqOqfLDx
  107. S66kbeFH0u86jm1hZibki7pfxLbxvu7KQgPe0meO5/13Retztz7/xa/pWIY71Zqd
  108. YC8UckuQdWUTxfuQf0470lAK34GZlDy9tvdVOG/PmNkG4j6OQjy0Kmz4Uk7rewKo
  109. ZbdphaLPJ2A4Rdqfn4WCoyDnxlfV861T922/dEDZEbNWiQpB81G8OfLL+FLHxyIT
  110. LKEu4R0CgYEA4RDj9jatJ/wGkMZBt+UF05mcJlRVMEijqdKgFwR2PP8b924Ka1mj
  111. 9zqWsfbxQbdPdwsCeVBZrSlTEmuFSQLeWtqBxBKBTps/tUP0qZf7HjfSmcVI89WE
  112. 3ab8LFjfh4PtK/LOq2D1GRZZkFliqi0gKwYdDoK6gxXWwrumXq4c2l8CgYEA8vrX
  113. dMuGCNDjNQkGXx3sr8pyHCDrSNR4Z4FrSlVUkgAW1L7FrCM911BuGh86FcOu9O/1
  114. Ggo0E8ge7qhQiXhB5vOo7hiVzSp0FxxCtGSlpdp4W6wx6ZWK8+Pc+6Moos03XdG7
  115. MKsdPGDciUn9VMOP3r8huX/btFTh90C/L50sH/cCgYAd02wyW8qUqux/0RYydZJR
  116. GWE9Hx3u+SFfRv9aLYgxyyj8oEOXOFjnUYdY7D3KlK1ePEJGq2RG81wD6+XM6Clp
  117. Zt2di0pBjYdi0S+iLfbkaUdqg1+ImLoz2YY/pkNxJQWQNmw2//FbMsAJxh6yKKrD
  118. qNq+6oonBwTf55hDodVHBwKBgEHgEBnyM9ygBXmTgM645jqiwF0v75pHQH2PcO8u
  119. Q0dyDr6PGjiZNWLyw2cBoFXWP9DYXbM5oPTcBMbfizY6DGP5G4uxzqtZHzBE0TDn
  120. OKHGoWr5PG7/xDRrSrZOfe3lhWVCP2XqfnqoKCJwlOYuPws89n+8UmyJttm6DBt0
  121. mUnxAoGBAIvbR87ZFXkvqstLs4KrdqTz4TQIcpzB3wENukHODPA6C1gzWTqp+OEe
  122. GMNltPfGCLO+YmoMQuTpb0kECYV3k4jR3gXO6YvlL9KbY+UOA6P0dDX4ROi2Rklj
  123. yh+lxFLYa1vlzzi9r8B7nkR9hrOGMvkfXF42X89g7lx4uMtu2I4q
  124. -----END RSA PRIVATE KEY-----`)