func AllIssuesHandlers()

in aws_signing_helper/serve.go [151:271]


func AllIssuesHandlers(cred *RefreshableCred, roleName string, opts *CredentialsOpts, signer Signer, signatureAlgorithm string) (http.HandlerFunc, http.HandlerFunc, http.HandlerFunc) {
	// Handles PUT requests to /latest/api/token/
	putTokenHandler := func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "PUT" {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}

		// Check for the presence of the X-Forwarded-For header
		xForwardedForHeader := r.Header.Get(X_FORWARDED_FOR_HEADER) // canonicalized headers are used (casing doesn't matter)
		if xForwardedForHeader != "" {
			w.WriteHeader(http.StatusBadRequest)
			io.WriteString(w, "unable to process requests with X-Forwarded-For header")
			return
		}

		// Obtain the token TTL
		tokenTTLStr := r.Header.Get(EC2_METADATA_TOKEN_TTL_HEADER)
		if tokenTTLStr == "" {
			tokenTTLStr = DEFAULT_TOKEN_TTL_SECONDS
		}
		tokenTTL, err := strconv.Atoi(tokenTTLStr)
		if err != nil || tokenTTL < 1 || tokenTTL > 21600 {
			w.WriteHeader(http.StatusBadRequest)
			io.WriteString(w, "invalid token TTL")
			return
		}

		// Generate token and insert it into map
		token, err := GenerateToken(100)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			io.WriteString(w, "unable to generate token")
			return
		}
		expirationTime := time.Now().Add(time.Second * time.Duration(tokenTTL))
		InsertToken(token, expirationTime)

		w.Header().Set(EC2_METADATA_TOKEN_TTL_HEADER, tokenTTLStr)
		io.WriteString(w, token) // nosemgrep
	}

	// Handles requests to /latest/meta-data/iam/security-credentials/
	getRoleNameHandler := func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}

		err := CheckValidToken(w, r)
		if err != nil {
			return
		}

		tokenTTL, err := FindTokenTTLSeconds(r)
		if err != nil {
			w.WriteHeader(http.StatusUnauthorized)
			return
		}
		w.Header().Set(EC2_METADATA_TOKEN_TTL_HEADER, tokenTTL)
		io.WriteString(w, roleName) // nosemgrep
	}

	// Handles GET requests to /latest/meta-data/iam/security-credentials/<ROLE_NAME>
	getCredentialsHandler := func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}

		err := CheckValidToken(w, r)
		if err != nil {
			log.Printf("Token validation received error: %s\n", err)
			return
		}

		var nextRefreshTime = cred.Expiration.Add(-RefreshTime)
		if time.Until(nextRefreshTime) < RefreshTime {
			if Debug {
				log.Println("Generating credentials")
			}
			credentialProcessOutput, gcErr := GenerateCredentials(opts, signer, signatureAlgorithm)
			if gcErr != nil {
				log.Printf("Error generating credentials: %s\n", gcErr)
			}
			cred.AccessKeyId = credentialProcessOutput.AccessKeyId
			cred.SecretAccessKey = credentialProcessOutput.SecretAccessKey
			cred.Token = credentialProcessOutput.SessionToken
			cred.Expiration, _ = time.Parse(time.RFC3339, credentialProcessOutput.Expiration)
			cred.Code = REFRESHABLE_CRED_CODE
			cred.LastUpdated = time.Now()
			cred.Type = REFRESHABLE_CRED_TYPE
			err := json.NewEncoder(w).Encode(cred)

			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				io.WriteString(w, "failed to encode credentials")
				return
			}
		} else {
			if Debug {
				log.Println("Using previously obtained credentials")
			}
			err := json.NewEncoder(w).Encode(cred)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				io.WriteString(w, "failed to encode credentials")
				return
			}
		}

		tokenTTL, err := FindTokenTTLSeconds(r)
		if err != nil {
			w.WriteHeader(http.StatusUnauthorized)
			return
		}
		w.Header().Set(EC2_METADATA_TOKEN_TTL_HEADER, tokenTTL)
	}

	return putTokenHandler, getRoleNameHandler, getCredentialsHandler
}