Browse code
Rework mfa authentication to take advantage of arn utilities
Edward Langley authored on 25/10/2019 22:08:07
Showing 2 changed files
Showing 2 changed files
... | ... |
@@ -6,15 +6,6 @@ |
6 | 6 |
|
7 | 7 |
(defparameter *user_management_account_id* 597974043991) |
8 | 8 |
|
9 |
-(defun mfa-serial-number (account user) |
|
10 |
- (format nil "arn:aws:iam::~a:mfa/~a" |
|
11 |
- account |
|
12 |
- user)) |
|
13 |
- |
|
14 |
-(defun role-arn (account role) |
|
15 |
- (format nil "arn:aws:iam::~a:role/cjorganization/~a" |
|
16 |
- account |
|
17 |
- role)) |
|
18 | 9 |
(defclass cj-organization-role () |
19 | 10 |
((account :initarg :account |
20 | 11 |
:reader account |
... | ... |
@@ -51,23 +42,17 @@ |
51 | 42 |
(finish-output *query-io*) |
52 | 43 |
(list (read-line *query-io*))) |
53 | 44 |
|
54 |
-(defun do-auth (user role token account) |
|
55 |
- (let ((mfa-serial-number |
|
56 |
- (mfa-serial-number *user_management_account_id* |
|
57 |
- user)) |
|
58 |
- (role-arn (role-arn account role))) |
|
59 |
- (loop |
|
60 |
- (restart-case |
|
61 |
- (return |
|
62 |
- (aws/sts:assume-role :role-arn role-arn |
|
63 |
- :role-session-name (session-name) |
|
64 |
- :serial-number mfa-serial-number |
|
65 |
- :duration-seconds #.(* 12 60 60) |
|
66 |
- :token-code token)) |
|
67 |
- (change-mfa-token (new-token) |
|
68 |
- :interactive read-new-mfa-token |
|
69 |
- (setf token new-token)) |
|
70 |
- (continue ()))))) |
|
45 |
+(defun do-auth (user role token) |
|
46 |
+ (with-retry (let ((mfa-serial-number (arn-for :mfa *user_management_account_id* user)) |
|
47 |
+ (role-arn (cj-organization-role-arn role))) |
|
48 |
+ (aws/sts:assume-role :role-arn role-arn |
|
49 |
+ :role-session-name (session-name) |
|
50 |
+ :serial-number mfa-serial-number |
|
51 |
+ :duration-seconds #.(* 12 60 60) |
|
52 |
+ :token-code token)) |
|
53 |
+ (change-mfa-token (new-token) |
|
54 |
+ :interactive read-new-mfa-token |
|
55 |
+ (setf token new-token)))) |
|
71 | 56 |
|
72 | 57 |
(defun change-mfa-token (new-value) |
73 | 58 |
(when (find-restart 'change-mfa-token) |
... | ... |
@@ -104,10 +89,10 @@ |
104 | 89 |
|
105 | 90 |
(defgeneric session-credentials (source) |
106 | 91 |
(:method ((source sts-result-handler)) |
107 |
- (aws-sdk:make-credentials |
|
108 |
- :access-key-id (session-id source) |
|
109 |
- :secret-access-key (session-key source) |
|
110 |
- :session-token (session-token source)))) |
|
92 |
+ (aws-sdk:make-credentials |
|
93 |
+ :access-key-id (session-id source) |
|
94 |
+ :secret-access-key (session-key source) |
|
95 |
+ :session-token (session-token source)))) |
|
111 | 96 |
|
112 | 97 |
(defun url-from-signin-token (signin-token) |
113 | 98 |
(format nil "https://signin.aws.amazon.com/federation?Action=login&Destination=https%3A%2F%2Fconsole.aws.amazon.com&SigninToken=~a" |
... | ... |
@@ -123,42 +108,33 @@ |
123 | 108 |
(finish-output *query-io*) |
124 | 109 |
(collect (read-line *query-io*)))) |
125 | 110 |
|
126 |
-(defun run-process (account user token) |
|
127 |
- (loop |
|
128 |
- (restart-bind ((set-aws-credentials (lambda (access-key-id secret-access-key) |
|
129 |
- (setf aws:*session* |
|
130 |
- (aws:make-session |
|
131 |
- :credentials (aws:make-credentials |
|
132 |
- :access-key-id access-key-id |
|
133 |
- :secret-access-key secret-access-key |
|
134 |
- :session-token nil |
|
135 |
- :provider-name "restart-provider"))) |
|
136 |
- (continue)) |
|
137 |
- :interactive-function 'read-new-aws-credentials |
|
138 |
- :report-function (lambda (s) |
|
139 |
- (princ "Supply new AWS credentials" s)) |
|
140 |
- :test-function (lambda (c) |
|
141 |
- (and (find-restart 'continue) |
|
142 |
- (typep c 'aws:no-credentials))))) |
|
143 |
- (let* ((api-result (cells:c-in (do-auth user "CJDeveloperAccessRole" token account))) |
|
144 |
- (parser (make-instance 'sts-result-handler :api-result api-result)) |
|
145 |
- (federation-url (url parser)) |
|
146 |
- (signin-token (gethash "SigninToken" |
|
147 |
- (yason:parse |
|
148 |
- (dexador:get federation-url))))) |
|
149 |
- (return-from run-process |
|
150 |
- (values signin-token |
|
151 |
- parser)))))) |
|
111 |
+(defun run-process (user role token) |
|
112 |
+ (with-retry* ((set-aws-credentials (lambda (access-key-id secret-access-key) |
|
113 |
+ (setf aws:*session* |
|
114 |
+ (aws:make-session |
|
115 |
+ :credentials (aws:make-credentials |
|
116 |
+ :access-key-id access-key-id |
|
117 |
+ :secret-access-key secret-access-key |
|
118 |
+ :session-token nil |
|
119 |
+ :provider-name "restart-provider"))) |
|
120 |
+ (continue)) |
|
121 |
+ :interactive-function 'read-new-aws-credentials |
|
122 |
+ :report-function (lambda (s) |
|
123 |
+ (princ "Supply new AWS credentials" s)) |
|
124 |
+ :test-function (lambda (c) |
|
125 |
+ (and (find-restart 'continue) |
|
126 |
+ (typep c 'aws:no-credentials))))) |
|
127 |
+ (let* ((api-result (cells:c-in (do-auth user role token))) |
|
128 |
+ (parser (make-instance 'sts-result-handler :api-result api-result)) |
|
129 |
+ (federation-url (url parser)) |
|
130 |
+ (signin-token (gethash "SigninToken" |
|
131 |
+ (yason:parse |
|
132 |
+ (dexador:get federation-url))))) |
|
133 |
+ (values signin-token |
|
134 |
+ parser)))) |
|
152 | 135 |
|
153 | 136 |
(defun set-aws-credentials (access-key-id secret-access-key &optional condition) |
154 |
- (alexandria:when-let ((restart (find-restart 'set-aws-credentials condition))) |
|
155 |
- (invoke-restart restart access-key-id secret-access-key))) |
|
156 |
- |
|
157 |
-(defun open-url (url) |
|
158 |
- (capi:contain (make-instance 'capi:browser-pane |
|
159 |
- :url url) |
|
160 |
- :best-width 1280 |
|
161 |
- :best-height 800)) |
|
137 |
+ (safely-invoke-restart 'set-aws-credentials condition access-key-id secret-access-key)) |
|
162 | 138 |
|
163 | 139 |
(defun sts-error-value (sts-response) |
164 | 140 |
(let ((parsed-error (dom:first-child |
... | ... |
@@ -34,7 +34,7 @@ |
34 | 34 |
:secret-access-key secret-access-key |
35 | 35 |
:session-token nil)))) |
36 | 36 |
|
37 |
-(defun authenticate (account user-name token) |
|
37 |
+(defun authenticate (user-name role token) |
|
38 | 38 |
(handler-bind ((aws-sdk:no-credentials |
39 | 39 |
(lambda (c) |
40 | 40 |
(alexandria:when-let |
... | ... |
@@ -42,7 +42,9 @@ |
42 | 42 |
(set-aws-credentials (mfa-tool.read-credentials:access-key result) |
43 | 43 |
(mfa-tool.read-credentials:secret-access-key result) |
44 | 44 |
c))))) |
45 |
- (run-process account user-name token))) |
|
45 |
+ (run-process user-name |
|
46 |
+ role |
|
47 |
+ token))) |
|
46 | 48 |
|
47 | 49 |
(defun go-on (_ interface) |
48 | 50 |
(declare (ignore _)) |
... | ... |
@@ -66,7 +68,9 @@ |
66 | 68 |
new-code) |
67 | 69 |
(change-mfa-token new-code)) |
68 | 70 |
(capi:abort-callback))))))) |
69 |
- (authenticate account user-name token)) |
|
71 |
+ (authenticate user-name |
|
72 |
+ (cj-developer-role account) |
|
73 |
+ token)) |
|
70 | 74 |
(with-open-file (stream (make-pathname :name "" |
71 | 75 |
:type "cj-aws" |
72 | 76 |
:defaults (user-homedir-pathname)) |