diff options
Diffstat (limited to 'app/controllers/api_credentials.go')
-rw-r--r-- | app/controllers/api_credentials.go | 84 |
1 files changed, 75 insertions, 9 deletions
diff --git a/app/controllers/api_credentials.go b/app/controllers/api_credentials.go index cd1a912..d53565e 100644 --- a/app/controllers/api_credentials.go +++ b/app/controllers/api_credentials.go | |||
@@ -1,7 +1,9 @@ | |||
1 | package controllers | 1 | package controllers |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "bytes" | ||
4 | "net/http" | 5 | "net/http" |
6 | "text/template" | ||
5 | "time" | 7 | "time" |
6 | 8 | ||
7 | "code.crute.us/mcrute/cloud-identity-broker/cloud/aws" | 9 | "code.crute.us/mcrute/cloud-identity-broker/cloud/aws" |
@@ -23,8 +25,33 @@ type jsonCredential struct { | |||
23 | SecretAccessKey *string `json:"secret_key"` | 25 | SecretAccessKey *string `json:"secret_key"` |
24 | SessionToken *string `json:"session_token"` | 26 | SessionToken *string `json:"session_token"` |
25 | Expiration *time.Time `json:"expiration"` | 27 | Expiration *time.Time `json:"expiration"` |
28 | ShortName string `json:"-"` | ||
26 | } | 29 | } |
27 | 30 | ||
31 | var ( | ||
32 | bashTemplate = template.Must(template.New("").Parse( | ||
33 | `export AWS_CREDS_EXPIRATION="{{ .Expiration }}" | ||
34 | export AWS_ACCESS_KEY_ID="{{ .AccessKeyId }}" | ||
35 | export AWS_SECRET_ACCESS_KEY="{{ .SecretAccessKey }}" | ||
36 | export AWS_SESSION_TOKEN="{{ .SessionToken }}" | ||
37 | `)) | ||
38 | |||
39 | pslTemplate = template.Must(template.New("").Parse( | ||
40 | `Set-Item -path env:AWS_CREDS_EXPIRATION -value '{{ .Expiration }}' | ||
41 | Set-Item -path env:AWS_ACCESS_KEY_ID -value '{{ .AccessKeyId }}' | ||
42 | Set-Item -path env:AWS_SECRET_ACCESS_KEY -value '{{ .SecretAccessKey }}' | ||
43 | Set-Item -path env:AWS_SESSION_TOKEN -value '{{ .SessionToken }}' | ||
44 | `)) | ||
45 | |||
46 | iniTemplate = template.Must(template.New("").Parse( | ||
47 | `[profile {{ .ShortName }}] | ||
48 | aws_access_key_id={{ .AccessKeyId }} | ||
49 | aws_secret_access_key={{ .SecretAccessKey }} | ||
50 | aws_session_token={{ .SessionToken }} | ||
51 | expiration={{ .Expiration }} | ||
52 | `)) | ||
53 | ) | ||
54 | |||
28 | type APICredentialsHandler struct { | 55 | type APICredentialsHandler struct { |
29 | *AWSAPI | 56 | *AWSAPI |
30 | } | 57 | } |
@@ -32,29 +59,32 @@ type APICredentialsHandler struct { | |||
32 | func NewAPICredentialsHandler(a *AWSAPI) echo.HandlerFunc { | 59 | func NewAPICredentialsHandler(a *AWSAPI) echo.HandlerFunc { |
33 | al := &APICredentialsHandler{a} | 60 | al := &APICredentialsHandler{a} |
34 | h := &controller.ContentTypeNegotiatingHandler{ | 61 | h := &controller.ContentTypeNegotiatingHandler{ |
35 | DefaultHandler: al.Handle, | 62 | DefaultHandler: al.HandleJSONV1, |
36 | Handlers: map[string]echo.HandlerFunc{ | 63 | Handlers: map[string]echo.HandlerFunc{ |
37 | contentTypeV1: al.Handle, | 64 | contentTypeV1: al.HandleJSONV1, |
38 | contentTypeV2: al.Handle, | 65 | contentTypeV2: al.HandleJSONV1, |
66 | contentTypeV2AWSBash: al.HandleBashV2, | ||
67 | contentTypeV2AWSPowershell: al.HandlePSLV2, | ||
68 | contentTypeV2AWSConfig: al.HandleINIV2, | ||
39 | }, | 69 | }, |
40 | } | 70 | } |
41 | return h.Handle | 71 | return h.Handle |
42 | } | 72 | } |
43 | 73 | ||
44 | func (h *APICredentialsHandler) Handle(c echo.Context) error { | 74 | func (h *APICredentialsHandler) getAWSCredential(c echo.Context) (*jsonCredential, error) { |
45 | rc, err := h.GetContext(c) // Does authorization checks | 75 | rc, err := h.GetContext(c) // Does authorization checks |
46 | if err != nil { | 76 | if err != nil { |
47 | return err | 77 | return nil, err |
48 | } | 78 | } |
49 | 79 | ||
50 | region := c.Param("region") | 80 | region := c.Param("region") |
51 | creds, err := rc.AWS.AssumeRole(rc.Principal.Username, ®ion) | 81 | creds, err := rc.AWS.AssumeRole(rc.Principal.Username, ®ion) |
52 | if err != nil { | 82 | if err != nil { |
53 | if aws.IsRegionNotExist(err) { | 83 | if aws.IsRegionNotExist(err) { |
54 | return echo.NotFoundHandler(c) | 84 | return nil, echo.NotFoundHandler(c) |
55 | } | 85 | } |
56 | c.Logger().Errorf("Error retrieving credentials: %w", err) | 86 | c.Logger().Errorf("Error retrieving credentials: %w", err) |
57 | return echo.ErrInternalServerError | 87 | return nil, echo.ErrInternalServerError |
58 | } | 88 | } |
59 | 89 | ||
60 | c.Logger().Infof( | 90 | c.Logger().Infof( |
@@ -68,10 +98,46 @@ func (h *APICredentialsHandler) Handle(c echo.Context) error { | |||
68 | 98 | ||
69 | c.Response().Header().Set("Expires", creds.Expiration.Add(-5*time.Minute).Format(time.RFC1123)) | 99 | c.Response().Header().Set("Expires", creds.Expiration.Add(-5*time.Minute).Format(time.RFC1123)) |
70 | 100 | ||
71 | return c.JSON(http.StatusOK, &jsonCredential{ | 101 | return &jsonCredential{ |
72 | AccessKeyId: creds.AccessKeyId, | 102 | AccessKeyId: creds.AccessKeyId, |
73 | SecretAccessKey: creds.SecretAccessKey, | 103 | SecretAccessKey: creds.SecretAccessKey, |
74 | SessionToken: creds.SessionToken, | 104 | SessionToken: creds.SessionToken, |
75 | Expiration: creds.Expiration, | 105 | Expiration: creds.Expiration, |
76 | }) | 106 | ShortName: rc.Account.ShortName, |
107 | }, nil | ||
108 | } | ||
109 | |||
110 | func (h *APICredentialsHandler) renderTemplate(c echo.Context, t *template.Template, ct string) error { | ||
111 | creds, err := h.getAWSCredential(c) | ||
112 | if err != nil { | ||
113 | return err | ||
114 | } | ||
115 | |||
116 | buf := &bytes.Buffer{} | ||
117 | if err = t.Execute(buf, creds); err != nil { | ||
118 | return echo.ErrInternalServerError | ||
119 | } | ||
120 | |||
121 | return c.Blob(http.StatusOK, ct, buf.Bytes()) | ||
122 | } | ||
123 | |||
124 | func (h *APICredentialsHandler) HandleJSONV1(c echo.Context) error { | ||
125 | creds, err := h.getAWSCredential(c) | ||
126 | if err != nil { | ||
127 | return err | ||
128 | } | ||
129 | |||
130 | return c.JSON(http.StatusOK, creds) | ||
131 | } | ||
132 | |||
133 | func (h *APICredentialsHandler) HandleBashV2(c echo.Context) error { | ||
134 | return h.renderTemplate(c, bashTemplate, contentTypeV2AWSBash) | ||
135 | } | ||
136 | |||
137 | func (h *APICredentialsHandler) HandlePSLV2(c echo.Context) error { | ||
138 | return h.renderTemplate(c, pslTemplate, contentTypeV2AWSPowershell) | ||
139 | } | ||
140 | |||
141 | func (h *APICredentialsHandler) HandleINIV2(c echo.Context) error { | ||
142 | return h.renderTemplate(c, iniTemplate, contentTypeV2AWSConfig) | ||
77 | } | 143 | } |