...

Source file src/k8s.io/kubernetes/pkg/routes/openidmetadata.go

Documentation: k8s.io/kubernetes/pkg/routes

     1  /*
     2  Copyright 2019 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  package routes
    18  
    19  import (
    20  	"net/http"
    21  
    22  	restful "github.com/emicklei/go-restful/v3"
    23  
    24  	"k8s.io/klog/v2"
    25  	"k8s.io/kubernetes/pkg/serviceaccount"
    26  )
    27  
    28  // This code is in package routes because many controllers import
    29  // pkg/serviceaccount, but are not allowed by import-boss to depend on
    30  // go-restful. All logic that deals with keys is kept in pkg/serviceaccount,
    31  // and only the rendered JSON is passed into this server.
    32  
    33  const (
    34  	// cacheControl is the value of the Cache-Control header. Overrides the
    35  	// global `private, no-cache` setting.
    36  	headerCacheControl = "Cache-Control"
    37  	cacheControl       = "public, max-age=3600" // 1 hour
    38  
    39  	// mimeJWKS is the content type of the keyset response
    40  	mimeJWKS = "application/jwk-set+json"
    41  )
    42  
    43  // OpenIDMetadataServer is an HTTP server for metadata of the KSA token issuer.
    44  type OpenIDMetadataServer struct {
    45  	configJSON []byte
    46  	keysetJSON []byte
    47  }
    48  
    49  // NewOpenIDMetadataServer creates a new OpenIDMetadataServer.
    50  // The issuer is the OIDC issuer; keys are the keys that may be used to sign
    51  // KSA tokens.
    52  func NewOpenIDMetadataServer(configJSON, keysetJSON []byte) *OpenIDMetadataServer {
    53  	return &OpenIDMetadataServer{
    54  		configJSON: configJSON,
    55  		keysetJSON: keysetJSON,
    56  	}
    57  }
    58  
    59  // Install adds this server to the request router c.
    60  func (s *OpenIDMetadataServer) Install(c *restful.Container) {
    61  	// Configuration WebService
    62  	// Container.Add "will detect duplicate root paths and exit in that case",
    63  	// so we need a root for /.well-known/openid-configuration to avoid conflicts.
    64  	cfg := new(restful.WebService).
    65  		Produces(restful.MIME_JSON)
    66  
    67  	cfg.Path(serviceaccount.OpenIDConfigPath).Route(
    68  		cfg.GET("").
    69  			To(fromStandard(s.serveConfiguration)).
    70  			Doc("get service account issuer OpenID configuration, also known as the 'OIDC discovery doc'").
    71  			Operation("getServiceAccountIssuerOpenIDConfiguration").
    72  			// Just include the OK, doesn't look like we include Internal Error in our openapi-spec.
    73  			Returns(http.StatusOK, "OK", ""))
    74  	c.Add(cfg)
    75  
    76  	// JWKS WebService
    77  	jwks := new(restful.WebService).
    78  		Produces(mimeJWKS)
    79  
    80  	jwks.Path(serviceaccount.JWKSPath).Route(
    81  		jwks.GET("").
    82  			To(fromStandard(s.serveKeys)).
    83  			Doc("get service account issuer OpenID JSON Web Key Set (contains public token verification keys)").
    84  			Operation("getServiceAccountIssuerOpenIDKeyset").
    85  			// Just include the OK, doesn't look like we include Internal Error in our openapi-spec.
    86  			Returns(http.StatusOK, "OK", ""))
    87  	c.Add(jwks)
    88  }
    89  
    90  // fromStandard provides compatibility between the standard (net/http) handler signature and the restful signature.
    91  func fromStandard(h http.HandlerFunc) restful.RouteFunction {
    92  	return func(req *restful.Request, resp *restful.Response) {
    93  		h(resp, req.Request)
    94  	}
    95  }
    96  
    97  func (s *OpenIDMetadataServer) serveConfiguration(w http.ResponseWriter, req *http.Request) {
    98  	w.Header().Set(restful.HEADER_ContentType, restful.MIME_JSON)
    99  	w.Header().Set(headerCacheControl, cacheControl)
   100  	if _, err := w.Write(s.configJSON); err != nil {
   101  		klog.Errorf("failed to write service account issuer metadata response: %v", err)
   102  		return
   103  	}
   104  }
   105  
   106  func (s *OpenIDMetadataServer) serveKeys(w http.ResponseWriter, req *http.Request) {
   107  	// Per RFC7517 : https://tools.ietf.org/html/rfc7517#section-8.5.1
   108  	w.Header().Set(restful.HEADER_ContentType, mimeJWKS)
   109  	w.Header().Set(headerCacheControl, cacheControl)
   110  	if _, err := w.Write(s.keysetJSON); err != nil {
   111  		klog.Errorf("failed to write service account issuer JWKS response: %v", err)
   112  		return
   113  	}
   114  }
   115  

View as plain text