Skip to content
This repository was archived by the owner on Oct 12, 2023. It is now read-only.

Commit 7e01970

Browse files
authored
fix: add handler for invalid token requests (#1325)
Signed-off-by: Anish Ramasekar <anish.ramasekar@gmail.com>
1 parent 4eb388a commit 7e01970

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

pkg/nmi/server/server.go

+24
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ const (
4040
headerRetryAfter = "Retry-After"
4141
)
4242

43+
var (
44+
// invalidTokenPathMatcher matches the token path that is not supported by IMDS
45+
// this handler is configured right after the token path handler to block requests with
46+
// invalid token path instead of sending it to IMDS.
47+
// we don't have to handle case sensitivity for "/identity/" as that's rejected by IMDS
48+
invalidTokenPathMatcher = mux.MatcherFunc(func(req *http.Request, rm *mux.RouteMatch) bool {
49+
r := regexp.MustCompile("/(?i:metadata)/identity(.*?)oauth2(.*?)token") // #nosec
50+
return r.MatchString(req.URL.Path)
51+
})
52+
)
53+
4354
// Server encapsulates all of the parameters necessary for starting up
4455
// the server. These can be set via command line.
4556
type Server struct {
@@ -98,7 +109,15 @@ func (s *Server) Run() error {
98109
go s.updateIPTableRules()
99110

100111
rtr := mux.NewRouter()
112+
// Flow for the request is as follows:
113+
// 1. If the request is for token, then it will be handled by tokenHandler post validation.
114+
// 2. If the request is for token but the path is invalid, then it will be handled by invalidTokenPathHandler.
115+
// 3. If the request is for host token, then it will be handled by hostTokenHandler.
116+
// 4. If the request is for instance metadata
117+
// 4.1 If blockInstanceMetadata is set to true, then it will be handled by blockInstanceMetadataHandler (deny access to instance metadata).
118+
// 5. If the request is for any other path, it will be proxied to IMDS and the response will be returned to the caller.
101119
rtr.PathPrefix(tokenPathPrefix).Handler(appHandler(s.msiHandler))
120+
rtr.MatcherFunc(invalidTokenPathMatcher).HandlerFunc(invalidTokenPathHandler)
102121
rtr.PathPrefix(hostTokenPathPrefix).Handler(appHandler(s.hostHandler))
103122
if s.BlockInstanceMetadata {
104123
rtr.PathPrefix(instancePathPrefix).HandlerFunc(forbiddenHandler)
@@ -581,6 +600,11 @@ func forbiddenHandler(w http.ResponseWriter, r *http.Request) {
581600
http.Error(w, "Request blocked by AAD Pod Identity NMI", http.StatusForbidden)
582601
}
583602

603+
// invalidTokenPathHandler responds to invalid token requests with HTTP 400 Bad Request
604+
func invalidTokenPathHandler(w http.ResponseWriter, r *http.Request) {
605+
http.Error(w, "Invalid request", http.StatusBadRequest)
606+
}
607+
584608
func copyHeader(dst, src http.Header) {
585609
for k, vv := range src {
586610
for _, v := range vv {

pkg/nmi/server/server_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,36 @@ func TestRouterPathPrefix(t *testing.T) {
217217
expectedStatusCode: http.StatusOK,
218218
expectedBody: "default_handler",
219219
},
220+
{
221+
name: "invalid token request with \\oauth2",
222+
url: `/metadata/identity\oauth2/token/`,
223+
expectedStatusCode: http.StatusOK,
224+
expectedBody: "invalid_request_handler",
225+
},
226+
{
227+
name: "invalid token request with \\token",
228+
url: `/metadata/identity/oauth2\token/`,
229+
expectedStatusCode: http.StatusOK,
230+
expectedBody: "invalid_request_handler",
231+
},
232+
{
233+
name: "invalid token request with \\oauth2\\token",
234+
url: `/metadata/identity\oauth2\token/`,
235+
expectedStatusCode: http.StatusOK,
236+
expectedBody: "invalid_request_handler",
237+
},
238+
{
239+
name: "invalid token request with mix of / and \\",
240+
url: `/metadata/identity/\oauth2\token/`,
241+
expectedStatusCode: http.StatusOK,
242+
expectedBody: "invalid_request_handler",
243+
},
244+
{
245+
name: "invalid token request with multiple \\",
246+
url: `/metadata/identity\\\oauth2\\token/`,
247+
expectedStatusCode: http.StatusOK,
248+
expectedBody: "invalid_request_handler",
249+
},
220250
}
221251

222252
for _, test := range tests {
@@ -225,6 +255,7 @@ func TestRouterPathPrefix(t *testing.T) {
225255
defer teardown()
226256

227257
rtr.PathPrefix(tokenPathPrefix).HandlerFunc(testTokenHandler)
258+
rtr.MatcherFunc(invalidTokenPathMatcher).HandlerFunc(testInvalidRequestHandler)
228259
rtr.PathPrefix(hostTokenPathPrefix).HandlerFunc(testHostTokenHandler)
229260
rtr.PathPrefix(instancePathPrefix).HandlerFunc(testInstanceHandler)
230261
rtr.PathPrefix("/").HandlerFunc(testDefaultHandler)
@@ -263,3 +294,7 @@ func testInstanceHandler(w http.ResponseWriter, r *http.Request) {
263294
func testDefaultHandler(w http.ResponseWriter, r *http.Request) {
264295
fmt.Fprintf(w, "default_handler\n")
265296
}
297+
298+
func testInvalidRequestHandler(w http.ResponseWriter, r *http.Request) {
299+
fmt.Fprintf(w, "invalid_request_handler\n")
300+
}

0 commit comments

Comments
 (0)