pkg/handlers/eks_credential_handler.go (91 lines of code) (raw):

package handlers import ( "context" "encoding/json" "net/http" "strconv" "time" "github.com/aws/aws-sdk-go-v2/aws" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "go.amzn.com/eks/eks-pod-identity-agent/internal/cloud/eksauth" "go.amzn.com/eks/eks-pod-identity-agent/internal/credsretriever" "go.amzn.com/eks/eks-pod-identity-agent/internal/middleware/logger" "go.amzn.com/eks/eks-pod-identity-agent/internal/validation" "go.amzn.com/eks/eks-pod-identity-agent/pkg/credentials" "go.amzn.com/eks/eks-pod-identity-agent/pkg/errors" ) type EksCredentialHandler struct { // ClusterName is the EKS cluster name where the agent runs ClusterName string // RequestValidator does basic validations for parameters that we are // going to send to EKS Auth. Note that these validations are very // rough and will never be as thorough as the ones done in the server RequestValidator validation.RequestValidator // CredentialRetriever will call EksAuthService to retrieve credentials CredentialRetriever credentials.CredentialRetriever } type EksCredentialHandlerOpts struct { Cfg aws.Config ClusterName string CredentialRenewal time.Duration MaxCacheSize int RefreshQPS int } var ( promHttpStatus = promauto.NewCounterVec(prometheus.CounterOpts{ Name: "pod_identity_http_response", Help: "Pod Identity http response code", }, []string{"code"}) ) func NewEksCredentialHandler(opts EksCredentialHandlerOpts) *EksCredentialHandler { credentialsRetriever := eksauth.NewService(opts.Cfg) if opts.CredentialRenewal != 0 && opts.MaxCacheSize != 0 { credentialsRetriever = credsretriever.NewCachedCredentialRetriever(credsretriever.CachedCredentialRetrieverOpts{ Delegate: credentialsRetriever, CredentialsRenewalTtl: opts.CredentialRenewal, MaxCacheSize: opts.MaxCacheSize, RefreshQPS: opts.RefreshQPS, }) } return &EksCredentialHandler{ RequestValidator: validation.DefaultCredentialValidator{}, ClusterName: opts.ClusterName, CredentialRetriever: credentialsRetriever, } } func (h *EksCredentialHandler) ConfigureHandler(register func(pattern string, handlerFunc http.HandlerFunc)) { register("/v1/credentials", h.HandleRequest) } func (h *EksCredentialHandler) HandleRequest(resp http.ResponseWriter, req *http.Request) { ctx := logger.ContextWithField(req.Context(), "cluster-name", h.ClusterName) log := logger.FromContext(ctx) log.Infof("handling new request request from %s", req.RemoteAddr) eksCredentialsRequest := &credentials.EksCredentialsRequest{ ClusterName: h.ClusterName, ServiceAccountToken: req.Header.Get("Authorization"), RequestTargetHost: req.Host, } creds, err := h.GetEksCredentials(ctx, eksCredentialsRequest) if err != nil { msg, code := errors.HandleCredentialFetchingError(ctx, err) promHttpStatus.WithLabelValues(strconv.Itoa(code)).Inc() http.Error(resp, msg, code) return } jsonOutput, err := json.Marshal(creds) if err != nil { promHttpStatus.WithLabelValues(strconv.Itoa(http.StatusInternalServerError)).Inc() http.Error(resp, "Unable to serialize credentials", http.StatusInternalServerError) return } // send the response resp.Header().Add("Content-Type", "application/json") promHttpStatus.WithLabelValues("200").Inc() _, err = resp.Write(jsonOutput) if err != nil { log.Errorf("failed to write response: %v", err) } } func (h *EksCredentialHandler) GetEksCredentials(ctx context.Context, request *credentials.EksCredentialsRequest) (*credentials.EksCredentialsResponse, error) { // validate request err := h.RequestValidator.ValidateEksCredentialRequest(ctx, request) if err != nil { return nil, err } // call EKS Auth iamCredentials, _, err := h.CredentialRetriever.GetIamCredentials(ctx, request) return iamCredentials, err }