k8s.io/kubernetes@v1.29.3/test/images/agnhost/porter/porter.go (about)

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // A tiny binary for testing ports.
    18  //
    19  // Reads env vars; for every var of the form SERVE_PORT_X, where X is a valid
    20  // port number, porter starts an HTTP server which serves the env var's value
    21  // in response to any query.
    22  
    23  package porter
    24  
    25  import (
    26  	"encoding/json"
    27  	"fmt"
    28  	"log"
    29  	"net/http"
    30  	"os"
    31  	"strings"
    32  
    33  	"github.com/ishidawataru/sctp"
    34  	"github.com/spf13/cobra"
    35  )
    36  
    37  const tcpPrefix = "SERVE_PORT_"
    38  const sctpPrefix = "SERVE_SCTP_PORT_"
    39  const tlsPrefix = "SERVE_TLS_PORT_"
    40  
    41  // CmdPorter is used by agnhost Cobra.
    42  var CmdPorter = &cobra.Command{
    43  	Use:   "porter",
    44  	Short: "Serves requested data on ports specified in ENV variables",
    45  	Long: `Serves requested data on ports specified in environment variables of the form SERVE_{PORT,TLS_PORT,SCTP_PORT}_[NNNN]. 
    46  	
    47  eg:
    48  * SERVE_PORT_9001 - serve TCP connections on port 9001
    49  * SERVE_TLS_PORT_9002 - serve TLS-encrypted TCP connections on port 9002
    50  * SERVE_SCTP_PORT_9003 - serve SCTP connections on port 9003
    51  
    52  The included "localhost.crt" is a PEM-encoded TLS cert with SAN IPs "127.0.0.1" and "[::1]", expiring in January 2084, generated from "src/crypto/tls".
    53  
    54  To use a different cert/key, mount them into the pod and set the "CERT_FILE" and "KEY_FILE" environment variables to the desired paths.`,
    55  	Args: cobra.MaximumNArgs(0),
    56  	Run:  main,
    57  }
    58  
    59  // JSONResponse enables --json-response flag
    60  var JSONResponse bool
    61  
    62  type jsonResponse struct {
    63  	Method string
    64  	Body   string
    65  }
    66  
    67  func init() {
    68  	CmdPorter.Flags().BoolVar(&JSONResponse, "json-response", false, "Responds to requests with a json response that includes the default value with the http.Request Method")
    69  }
    70  
    71  func main(cmd *cobra.Command, args []string) {
    72  	for _, vk := range os.Environ() {
    73  		// Put everything before the first = sign in parts[0], and
    74  		// everything else in parts[1] (even if there are multiple =
    75  		// characters).
    76  		parts := strings.SplitN(vk, "=", 2)
    77  		key := parts[0]
    78  		value := parts[1]
    79  
    80  		switch {
    81  		case strings.HasPrefix(key, tcpPrefix):
    82  			port := strings.TrimPrefix(key, tcpPrefix)
    83  			go servePort(port, value)
    84  		case strings.HasPrefix(key, sctpPrefix):
    85  			port := strings.TrimPrefix(key, sctpPrefix)
    86  			go serveSCTPPort(port, value)
    87  		case strings.HasPrefix(key, tlsPrefix):
    88  			port := strings.TrimPrefix(key, tlsPrefix)
    89  			go serveTLSPort(port, value)
    90  		}
    91  	}
    92  
    93  	select {}
    94  }
    95  
    96  func servePort(port, value string) {
    97  
    98  	s := &http.Server{
    99  		Addr: "0.0.0.0:" + port,
   100  		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   101  			body := value
   102  			if JSONResponse {
   103  				j, err := json.Marshal(&jsonResponse{
   104  					Method: r.Method,
   105  					Body:   value})
   106  				if err != nil {
   107  					http.Error(w, fmt.Sprintf("Internal Server Error: %v", err), 500)
   108  					return
   109  				}
   110  				w.Header().Set("Content-Type", "application/json")
   111  				body = string(j)
   112  			}
   113  			fmt.Fprint(w, body)
   114  		}),
   115  	}
   116  	log.Printf("server on port %q failed: %v", port, s.ListenAndServe())
   117  }
   118  
   119  func serveTLSPort(port, value string) {
   120  	s := &http.Server{
   121  		Addr: "0.0.0.0:" + port,
   122  		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   123  			body := value
   124  			if JSONResponse {
   125  				j, err := json.Marshal(&jsonResponse{
   126  					Method: r.Method,
   127  					Body:   value})
   128  				if err != nil {
   129  					http.Error(w, fmt.Sprintf("Internal Server Error: %v", err), 500)
   130  					return
   131  				}
   132  				w.Header().Set("Content-Type", "application/json")
   133  				body = string(j)
   134  			}
   135  			fmt.Fprint(w, body)
   136  		}),
   137  	}
   138  	certFile := os.Getenv("CERT_FILE")
   139  	if len(certFile) == 0 {
   140  		certFile = "localhost.crt"
   141  	}
   142  	keyFile := os.Getenv("KEY_FILE")
   143  	if len(keyFile) == 0 {
   144  		keyFile = "localhost.key"
   145  	}
   146  	log.Printf("tls server on port %q with certFile=%q, keyFile=%q failed: %v", port, certFile, keyFile, s.ListenAndServeTLS(certFile, keyFile))
   147  }
   148  
   149  func serveSCTPPort(port, value string) {
   150  	serverAddress, err := sctp.ResolveSCTPAddr("sctp", "0.0.0.0:"+port)
   151  	if err != nil {
   152  		log.Fatal("Sctp: failed to resolve address. error:", err)
   153  	}
   154  
   155  	listener, err := sctp.ListenSCTP("sctp", serverAddress)
   156  	if err != nil {
   157  		log.Fatal("Failed to listen SCTP. error:", err)
   158  	}
   159  	log.Printf("Started SCTP server")
   160  
   161  	defer listener.Close()
   162  	defer func() {
   163  		log.Printf("SCTP server exited")
   164  	}()
   165  
   166  	for {
   167  		conn, err := listener.AcceptSCTP()
   168  		if err != nil {
   169  			log.Fatal("Failed to accept SCTP. error:", err)
   170  		}
   171  		go func(conn *sctp.SCTPConn) {
   172  			defer conn.Close()
   173  			log.Println("Sending response")
   174  			_, err = conn.Write([]byte(value))
   175  			if err != nil {
   176  				log.Println("Failed to send response", err)
   177  				return
   178  			}
   179  			log.Println("Response sent")
   180  		}(conn)
   181  	}
   182  }