@@ -17,7 +17,7 @@ use micro_http::{
1717 Body , HttpHeaderError , MediaType , Method , Request , RequestError , Response , StatusCode , Version ,
1818} ;
1919use serde_json:: { Map , Value } ;
20- use token_headers:: TokenHeaders ;
20+ use token_headers:: { XMetadataToken , XMetadataTokenTtlSeconds } ;
2121
2222use crate :: mmds:: data_store:: { Mmds , MmdsDatastoreError as MmdsError , MmdsVersion , OutputFormat } ;
2323use crate :: mmds:: token:: PATH_TO_TOKEN ;
@@ -142,23 +142,10 @@ fn respond_to_request_mmdsv1(mmds: &Mmds, request: Request) -> Response {
142142}
143143
144144fn respond_to_request_mmdsv2 ( mmds : & mut Mmds , request : Request ) -> Response {
145- // Fetch custom headers from request.
146- let token_headers = match TokenHeaders :: try_from ( request. headers . custom_entries ( ) ) {
147- Ok ( token_headers) => token_headers,
148- Err ( err) => {
149- return build_response (
150- request. http_version ( ) ,
151- StatusCode :: BadRequest ,
152- MediaType :: PlainText ,
153- Body :: new ( err. to_string ( ) ) ,
154- ) ;
155- }
156- } ;
157-
158145 // Allow only GET and PUT requests.
159146 match request. method ( ) {
160- Method :: Get => respond_to_get_request_checked ( mmds, request, token_headers ) ,
161- Method :: Put => respond_to_put_request ( mmds, request, token_headers ) ,
147+ Method :: Get => respond_to_get_request_checked ( mmds, request) ,
148+ Method :: Put => respond_to_put_request ( mmds, request) ,
162149 _ => {
163150 let mut response = build_response (
164151 request. http_version ( ) ,
@@ -173,13 +160,10 @@ fn respond_to_request_mmdsv2(mmds: &mut Mmds, request: Request) -> Response {
173160 }
174161}
175162
176- fn respond_to_get_request_checked (
177- mmds : & Mmds ,
178- request : Request ,
179- token_headers : TokenHeaders ,
180- ) -> Response {
181- // Get MMDS token from custom headers.
182- let token = match token_headers. x_metadata_token ( ) {
163+ fn respond_to_get_request_checked ( mmds : & Mmds , request : Request ) -> Response {
164+ // Check whether a token exists.
165+ let x_metadata_token = XMetadataToken :: from ( request. headers . custom_entries ( ) ) ;
166+ let token = match x_metadata_token. 0 {
183167 Some ( token) => token,
184168 None => {
185169 let error_msg = VmmMmdsError :: NoTokenProvided . to_string ( ) ;
@@ -192,8 +176,8 @@ fn respond_to_get_request_checked(
192176 }
193177 } ;
194178
195- // Validate MMDS token.
196- match mmds. is_valid_token ( token) {
179+ // Validate the token.
180+ match mmds. is_valid_token ( & token) {
197181 Ok ( true ) => respond_to_get_request_unchecked ( mmds, request) ,
198182 Ok ( false ) => build_response (
199183 request. http_version ( ) ,
@@ -248,17 +232,11 @@ fn respond_to_get_request_unchecked(mmds: &Mmds, request: Request) -> Response {
248232 }
249233}
250234
251- fn respond_to_put_request (
252- mmds : & mut Mmds ,
253- request : Request ,
254- token_headers : TokenHeaders ,
255- ) -> Response {
235+ fn respond_to_put_request ( mmds : & mut Mmds , request : Request ) -> Response {
236+ let custom_headers = request. headers . custom_entries ( ) ;
237+
256238 // Reject `PUT` requests that contain `X-Forwarded-For` header.
257- if request
258- . headers
259- . custom_entries ( )
260- . contains_key ( REJECTED_HEADER )
261- {
239+ if custom_headers. contains_key ( REJECTED_HEADER ) {
262240 let error_msg = RequestError :: HeaderError ( HttpHeaderError :: UnsupportedName (
263241 REJECTED_HEADER . to_string ( ) ,
264242 ) )
@@ -287,16 +265,26 @@ fn respond_to_put_request(
287265 }
288266
289267 // Get token lifetime value.
290- let ttl_seconds = match token_headers. x_metadata_token_ttl_seconds ( ) {
291- Some ( ttl_seconds) => ttl_seconds,
292- None => {
268+ let ttl_seconds = match XMetadataTokenTtlSeconds :: try_from ( custom_headers) {
269+ Err ( err) => {
293270 return build_response (
294271 request. http_version ( ) ,
295272 StatusCode :: BadRequest ,
296273 MediaType :: PlainText ,
297- Body :: new ( VmmMmdsError :: NoTtlProvided . to_string ( ) ) ,
274+ Body :: new ( err . to_string ( ) ) ,
298275 ) ;
299276 }
277+ Ok ( ttl_seconds) => match ttl_seconds. 0 {
278+ Some ( ttl_seconds) => ttl_seconds,
279+ None => {
280+ return build_response (
281+ request. http_version ( ) ,
282+ StatusCode :: BadRequest ,
283+ MediaType :: PlainText ,
284+ Body :: new ( VmmMmdsError :: NoTtlProvided . to_string ( ) ) ,
285+ ) ;
286+ }
287+ } ,
300288 } ;
301289
302290 // Generate token.
@@ -530,7 +518,7 @@ mod tests {
530518 let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
531519 assert_eq ! ( actual_response, expected_response) ;
532520
533- // Test invalid custom header value is ignored when V1 is configured .
521+ // Test invalid custom header value is ignored if not PUT request to /latest/api/token .
534522 let ( request, expected_response) = generate_request_and_expected_response (
535523 b"GET http://169.254.169.254/ HTTP/1.0\r \n \
536524 Accept: application/json\r \n \
@@ -576,23 +564,6 @@ mod tests {
576564 let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
577565 assert_eq ! ( actual_response, expected_response) ;
578566
579- // Test invalid value for custom header.
580- let request = Request :: try_from (
581- b"GET http://169.254.169.254/ HTTP/1.0\r \n \
582- Accept: application/json\r \n \
583- X-metadata-token-ttl-seconds: -60\r \n \r \n ",
584- None ,
585- )
586- . unwrap ( ) ;
587- let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: BadRequest ) ;
588- expected_response. set_content_type ( MediaType :: PlainText ) ;
589- expected_response. set_body ( Body :: new (
590- "Invalid header. Reason: Invalid value. Key:X-metadata-token-ttl-seconds; Value:-60"
591- . to_string ( ) ,
592- ) ) ;
593- let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
594- assert_eq ! ( actual_response, expected_response) ;
595-
596567 // Test PUT requests.
597568 // Unsupported `X-Forwarded-For` header present.
598569 let request = Request :: try_from (
@@ -624,6 +595,22 @@ mod tests {
624595 let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
625596 assert_eq ! ( actual_response, expected_response) ;
626597
598+ // Test invalid X-metadata-token-ttl-seconds value gets BadRequest.
599+ let request = Request :: try_from (
600+ b"PUT http://169.254.169.254/latest/api/token HTTP/1.0\r \n \
601+ X-metadata-token-ttl-seconds: -60\r \n \r \n ",
602+ None ,
603+ )
604+ . unwrap ( ) ;
605+ let mut expected_response = Response :: new ( Version :: Http10 , StatusCode :: BadRequest ) ;
606+ expected_response. set_content_type ( MediaType :: PlainText ) ;
607+ expected_response. set_body ( Body :: new (
608+ "Invalid header. Reason: Invalid value. Key:X-metadata-token-ttl-seconds; Value:-60"
609+ . to_string ( ) ,
610+ ) ) ;
611+ let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
612+ assert_eq ! ( actual_response, expected_response) ;
613+
627614 // Test invalid lifetime values for token.
628615 let invalid_values = [ MIN_TOKEN_TTL_SECONDS - 1 , MAX_TOKEN_TTL_SECONDS + 1 ] ;
629616 for invalid_value in invalid_values. iter ( ) {
@@ -687,6 +674,21 @@ mod tests {
687674 let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
688675 assert_eq ! ( actual_response, expected_response) ;
689676
677+ // Test invalid customer header value is ignored if not PUT request to /latest/api/token.
678+ #[ rustfmt:: skip]
679+ let ( request, expected_response) = generate_request_and_expected_response (
680+ format ! (
681+ "GET http://169.254.169.254/ HTTP/1.0\r \n \
682+ Accept: application/json\r \n \
683+ X-metadata-token: {valid_token}\r \n \
684+ X-metadata-token-ttl-seconds: -60\r \n \r \n ",
685+ )
686+ . as_bytes ( ) ,
687+ MediaType :: ApplicationJson ,
688+ ) ;
689+ let actual_response = convert_to_response ( mmds. clone ( ) , request) ;
690+ assert_eq ! ( actual_response, expected_response) ;
691+
690692 // Test GET request towards unsupported value type.
691693 #[ rustfmt:: skip]
692694 let request = Request :: try_from (
0 commit comments