istio.io/istio@v0.0.0-20240520182934-d79c90f27776/samples/jwt-server/src/main.go (about)

     1  // Copyright Istio Authors
     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  package main
    16  
    17  import (
    18  	"flag"
    19  	"fmt"
    20  	"log"
    21  	"net"
    22  	"net/http"
    23  	"os"
    24  	"os/signal"
    25  	"sync"
    26  	"syscall"
    27  	"time"
    28  )
    29  
    30  const (
    31  	// nolint: lll
    32  	jwtKey = "{ \"keys\":[ {\"e\":\"AQAB\",\"kid\":\"tT_w9LRNrY7wJalGsTYSt7rutZi86Gvyc0EKR4CaQAw\",\"kty\":\"RSA\",\"n\":\"raJ7ZEhMfrBUo2werGKOow9an1B6Ukc6dKY2hNi10eaQe9ehJCjLpmJpePxoqaCi2VYt6gncLfhEV71JDGsodbfYMlaxwWTt6lXBcjlVXHWDXLC45rHVfi9FjSSXloHqmSStpjv3mrW3R6fx2VeVVP_mrA6ZHtcynq6ecJqO11STvVoeeM3lEsASVSWsUrKltC1Crfo0sI7YG34QjophVTEi8B9gVepAJZV-Bso5sinRABnxfLUM7DU5c8MO114uvXThgSIuAOM9PbViSC3X6Y9Gsjsy881HGO-EJaUCrwSWnwQW5sp0TktrYL70-M4_ug-X51Yt_PErmncKupx8Hw\"}]}"
    33  )
    34  
    35  var (
    36  	httpPort   = flag.String("http", "8000", "HTTP server port")
    37  	httpsPort  = flag.String("https", "8443", "HTTPS server port")
    38  	serverCert = flag.String("cert", "", "Optional, the name of server's certificate file")
    39  	serverkey  = flag.String("key", "", "Optional, the name of server's private key")
    40  )
    41  
    42  // JWTServer implements the sample server that serves jwt keys.
    43  type JWTServer struct {
    44  	httpServer *http.Server
    45  	// For test only
    46  	httpPort chan int
    47  	// For https test
    48  	httpsPort chan int
    49  	// https server certificate
    50  	serverCertificate string
    51  	// https server private key
    52  	serverPrivateKey string
    53  }
    54  
    55  // ServeHTTP serves the JWT Keys.
    56  func (s *JWTServer) ServeHTTP(response http.ResponseWriter, request *http.Request) {
    57  	// Add artificious delay based on delay query
    58  	delayParam := request.URL.Query().Get("delay")
    59  	if delayParam != "" {
    60  		delayDuration, err := time.ParseDuration(delayParam)
    61  		if err != nil {
    62  			// Handle invalid delay parameter
    63  			response.WriteHeader(http.StatusBadRequest)
    64  			response.Write([]byte("Invalid delay parameter"))
    65  			return
    66  		}
    67  
    68  		// If delay parameter is provided and valid, add delay
    69  		if delayDuration > 0 {
    70  			time.Sleep(delayDuration)
    71  		}
    72  	}
    73  
    74  	response.WriteHeader(http.StatusOK)
    75  	response.Write([]byte(string(jwtKey)))
    76  }
    77  
    78  func (s *JWTServer) startHTTP(address string, wg *sync.WaitGroup) {
    79  	defer func() {
    80  		wg.Done()
    81  		log.Printf("Stopped JWT HTTP server")
    82  	}()
    83  
    84  	listener, err := net.Listen("tcp", address)
    85  	if err != nil {
    86  		log.Fatalf("Failed to create HTTP server: %v", err)
    87  	}
    88  	// Store the port for test only.
    89  	s.httpPort <- listener.Addr().(*net.TCPAddr).Port
    90  	s.httpServer = &http.Server{Handler: s}
    91  
    92  	log.Printf("Starting HTTP server at %s", listener.Addr())
    93  	if err := s.httpServer.Serve(listener); err != nil {
    94  		log.Fatalf("Failed to start HTTP server: %v", err)
    95  	}
    96  }
    97  
    98  func (s *JWTServer) startHTTPS(address string, wg *sync.WaitGroup) {
    99  	defer func() {
   100  		wg.Done()
   101  		log.Printf("Stopped JWT HTTPS server")
   102  	}()
   103  
   104  	listener, err := net.Listen("tcp", address)
   105  	if err != nil {
   106  		log.Fatalf("Failed to create HTTPS server: %v", err)
   107  	}
   108  	// Store the port for test only.
   109  	s.httpsPort <- listener.Addr().(*net.TCPAddr).Port
   110  	s.httpServer = &http.Server{Handler: s}
   111  
   112  	log.Printf("Starting HTTPS server on port %s", address)
   113  	if err := s.httpServer.ServeTLS(listener, s.serverCertificate, s.serverPrivateKey); err != nil {
   114  		log.Fatalf("Failed to start HTTPS server: %v", err)
   115  	}
   116  }
   117  
   118  func (s *JWTServer) runHTTP(httpAddr string) {
   119  	var wg sync.WaitGroup
   120  	wg.Add(1)
   121  	go s.startHTTP(httpAddr, &wg)
   122  	wg.Wait()
   123  }
   124  
   125  func (s *JWTServer) runHTTPS(httpsAddr string) {
   126  	var wg sync.WaitGroup
   127  	wg.Add(1)
   128  	go s.startHTTPS(httpsAddr, &wg)
   129  	wg.Wait()
   130  }
   131  
   132  func (s *JWTServer) stop() {
   133  	s.httpServer.Close()
   134  }
   135  
   136  func NewJwtServer(certificate string, key string) *JWTServer {
   137  	return &JWTServer{
   138  		httpPort:          make(chan int, 1),
   139  		httpsPort:         make(chan int, 1),
   140  		serverCertificate: certificate,
   141  		serverPrivateKey:  key,
   142  	}
   143  }
   144  
   145  func main() {
   146  	flag.Parse()
   147  	s := NewJwtServer(*serverCert, *serverkey)
   148  	go s.runHTTP(fmt.Sprintf(":%s", *httpPort))
   149  	if s.serverCertificate != "" && s.serverPrivateKey != "" {
   150  		go s.runHTTPS(fmt.Sprintf(":%s", *httpsPort))
   151  	}
   152  	defer s.stop()
   153  
   154  	// Wait for the process to be shutdown.
   155  	sigs := make(chan os.Signal, 1)
   156  	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
   157  	<-sigs
   158  }