package controllers import ( "net/http" "time" "code.crute.us/mcrute/cloud-identity-broker/cloud/aws" "code.crute.us/mcrute/golib/echo/controller" "github.com/labstack/echo/v4" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) var credsAllowed = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: "aws_access", // Legacy namespace Name: "broker_cred_access_total", Help: "Total number of credential accesses allowed by broker", }, []string{"account", "region"}) type jsonCredential struct { AccessKeyId *string `json:"access_key"` SecretAccessKey *string `json:"secret_key"` SessionToken *string `json:"session_token"` Expiration *time.Time `json:"expiration"` } type APICredentialsHandler struct { *AWSAPI } func NewAPICredentialsHandler(a *AWSAPI) echo.HandlerFunc { al := &APICredentialsHandler{a} h := &controller.ContentTypeNegotiatingHandler{ DefaultHandler: al.Handle, Handlers: map[string]echo.HandlerFunc{ contentTypeV1: al.Handle, contentTypeV2: al.Handle, }, } return h.Handle } func (h *APICredentialsHandler) Handle(c echo.Context) error { rc, err := h.GetContext(c) // Does authorization checks if err != nil { return err } region := c.Param("region") creds, err := rc.AWS.AssumeRole(rc.Principal.Username, ®ion) if err != nil { if aws.IsRegionNotExist(err) { return echo.NotFoundHandler(c) } c.Logger().Errorf("Error retrieving credentials: %w", err) return echo.ErrInternalServerError } c.Logger().Infof( "Allowing '%s' to access account credential '%s'", rc.Principal.Username, rc.Account.Name, ) credsAllowed.With(prometheus.Labels{ "account": rc.Account.ShortName, "region": region, }).Inc() c.Response().Header().Set("Expires", creds.Expiration.Add(-5*time.Minute).Format(time.RFC1123)) return c.JSON(http.StatusOK, &jsonCredential{ AccessKeyId: creds.AccessKeyId, SecretAccessKey: creds.SecretAccessKey, SessionToken: creds.SessionToken, Expiration: creds.Expiration, }) }