Browse code
(init)
Edward Langley authored on 29/09/2019 22:37:07
Showing 12 changed files
Showing 12 changed files
- .gitignore
- Makefile
- aws-access.asd
- deliver.lisp
- flip-yaml.lisp
- icon/.gitignore
- icon/Makefile
- icon/icon.svg
- src/capi-interface.lisp
- src/domain.lisp
- src/mfa-tool.lisp
- src/package.lisp
0 | 7 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,15 @@ |
1 |
+CJAWSAccess.app: app.icns deliver.lisp src/*.lisp aws-access.asd accounts.json |
|
2 |
+ /Applications/LispWorks\ 7.1\ \(64-bit\)/LispWorks\ \(64-bit\).app/Contents/MacOS/lispworks-7-1-0-amd64-darwin -build deliver.lisp |
|
3 |
+ cp accounts.json CJAWSAccess.app/Contents/Resources/accounts.json |
|
4 |
+ cp app.icns CJAWSAccess.app/Contents/Resources/app.icns |
|
5 |
+ touch CJAWSAccess.app |
|
6 |
+ |
|
7 |
+accounts.json: accounts.yml |
|
8 |
+ ./flip-yaml.lisp accounts.yml |
|
9 |
+ |
|
10 |
+accounts.yml: |
|
11 |
+ git archive --format=tar --remote=git@gitlab.cj.com:operations-chapter/aws-department.git heads/master -- accounts.yaml | tar xO accounts.yaml > ~/accounts.yml |
|
12 |
+ |
|
13 |
+app.icns: icon/icon.svg |
|
14 |
+ $(MAKE) --directory=icon |
|
15 |
+ cp icon/icon.icns app.icns |
0 | 16 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,23 @@ |
1 |
+;;; -*- Mode:Lisp; Syntax:ANSI-Common-Lisp; Package: ASDF-USER -*- |
|
2 |
+(in-package :asdf-user) |
|
3 |
+ |
|
4 |
+(defsystem :aws-access |
|
5 |
+ :description "A simple tool for access to CJ's AWS accounts" |
|
6 |
+ :author "Ed L <edward@elangley.org>" |
|
7 |
+ :license "MIT" |
|
8 |
+ :depends-on (:alexandria |
|
9 |
+ :aws-sdk |
|
10 |
+ :aws-sdk/services/sts |
|
11 |
+ :cells |
|
12 |
+ :cl-yaml |
|
13 |
+ :fwoar-lisputils |
|
14 |
+ :serapeum |
|
15 |
+ :ubiquitous |
|
16 |
+ :uiop |
|
17 |
+ :yason) |
|
18 |
+ :serial t |
|
19 |
+ :components ((:module "src" |
|
20 |
+ :serial t |
|
21 |
+ :components ((:file "package") |
|
22 |
+ (:file "mfa-tool") |
|
23 |
+ (:file "capi-interface"))))) |
0 | 24 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,23 @@ |
1 |
+(in-package :cl-user) |
|
2 |
+(setf *default-pathname-defaults* |
|
3 |
+ (make-pathname :directory (pathname-directory *load-pathname*))) |
|
4 |
+(format t "~&CURDIR: ~a~%" (truename ".")) |
|
5 |
+(load-all-patches) |
|
6 |
+(load "~/quicklisp/setup.lisp") |
|
7 |
+(ql:quickload :swank) |
|
8 |
+(mapcar 'asdf:load-asd |
|
9 |
+ (directory "*.asd")) |
|
10 |
+(ql:quickload :aws-access) |
|
11 |
+ |
|
12 |
+(deliver (intern "MAIN" "MFA-TOOL") |
|
13 |
+ (create-macos-application-bundle |
|
14 |
+ "CJAWSAccess.app" |
|
15 |
+ :document-types nil |
|
16 |
+ :identifier "fwoar.cj.AWSAccess") |
|
17 |
+ 0 |
|
18 |
+ :KEEP-PRETTY-PRINTER t |
|
19 |
+ :interface :capi |
|
20 |
+ :keep-modules t |
|
21 |
+ :packages-to-keep-symbol-names '(:mfa-tool) |
|
22 |
+ :packages-to-keep '(:mfa-tool :swank) |
|
23 |
+ :startup-bitmap-file nil) |
0 | 24 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,23 @@ |
1 |
+#!/usr/bin/env sbcl --script |
|
2 |
+(eval-when (:compile-toplevel :load-toplevel :execute) |
|
3 |
+ (load "~/quicklisp/setup.lisp")) |
|
4 |
+ |
|
5 |
+(eval-when (:compile-toplevel :load-toplevel :execute) |
|
6 |
+ (ql:quickload '(:cl-yaml :yason :uiop :alexandria))) |
|
7 |
+ |
|
8 |
+(defparameter *in-file* |
|
9 |
+ (pathname (first (uiop:command-line-arguments)))) |
|
10 |
+ |
|
11 |
+(defparameter *out-file* |
|
12 |
+ (make-pathname :type "json" |
|
13 |
+ :defaults *in-file*)) |
|
14 |
+ |
|
15 |
+(format t "~a -> ~a" *in-file* *out-file*) |
|
16 |
+ |
|
17 |
+(defparameter *accounts-in* |
|
18 |
+ (alexandria:read-file-into-string *in-file*)) |
|
19 |
+ |
|
20 |
+(alexandria:with-output-to-file (out *out-file* :if-exists :supersede) |
|
21 |
+ (with-open-stream (out-stream (yason:make-json-output-stream out :indent t)) |
|
22 |
+ (yason:encode (cl-yaml:parse *accounts-in*) |
|
23 |
+ out-stream))) |
0 | 3 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,20 @@ |
1 |
+all: icon.iconset |
|
2 |
+ iconutil -c icns icon.iconset |
|
3 |
+ |
|
4 |
+icon.iconset: icon.svg |
|
5 |
+ rm -rf icon.iconset |
|
6 |
+ mkdir -p icon.iconset |
|
7 |
+ rsvg-convert -w 16 -h 16 icon.svg > icon.iconset/icon_16x16.png |
|
8 |
+ rsvg-convert -w 32 -h 32 icon.svg > icon.iconset/icon_16x16@2x.png |
|
9 |
+ rsvg-convert -w 32 -h 32 icon.svg > icon.iconset/icon_32x32.png |
|
10 |
+ rsvg-convert -w 64 -h 64 icon.svg > icon.iconset/icon_32x32@2x.png |
|
11 |
+ rsvg-convert -w 64 -h 64 icon.svg > icon.iconset/icon_64x64.png |
|
12 |
+ rsvg-convert -w 128 -h 128 icon.svg > icon.iconset/icon_64x64@2x.png |
|
13 |
+ rsvg-convert -w 128 -h 128 icon.svg > icon.iconset/icon_128x128.png |
|
14 |
+ rsvg-convert -w 256 -h 256 icon.svg > icon.iconset/icon_128x128@2x.png |
|
15 |
+ rsvg-convert -w 256 -h 256 icon.svg > icon.iconset/icon_256x256.png |
|
16 |
+ rsvg-convert -w 512 -h 512 icon.svg > icon.iconset/icon_256x256@2x.png |
|
17 |
+ rsvg-convert -w 512 -h 512 icon.svg > icon.iconset/icon_512x512.png |
|
18 |
+ rsvg-convert -w 1024 -h 1024 icon.svg > icon.iconset/icon_512x512@2x.png |
|
19 |
+ rsvg-convert -w 1024 -h 1024 icon.svg > icon.iconset/icon_1024x1024.png |
|
20 |
+ rsvg-convert -w 2048 -h 2048 icon.svg > icon.iconset/icon_1024x1024@2x.png |
0 | 21 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,253 @@ |
1 |
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|
2 |
+<svg |
|
3 |
+ xmlns:dc="http://purl.org/dc/elements/1.1/" |
|
4 |
+ xmlns:cc="http://creativecommons.org/ns#" |
|
5 |
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|
6 |
+ xmlns:svg="http://www.w3.org/2000/svg" |
|
7 |
+ xmlns="http://www.w3.org/2000/svg" |
|
8 |
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
|
9 |
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
|
10 |
+ xml:space="preserve" |
|
11 |
+ enable-background="new 0 0 1024 768" |
|
12 |
+ viewBox="0 0 1024 1024" |
|
13 |
+ height="1024" |
|
14 |
+ width="1024" |
|
15 |
+ y="0px" |
|
16 |
+ x="0px" |
|
17 |
+ id="Layer_1" |
|
18 |
+ version="1.1" |
|
19 |
+ sodipodi:docname="icon.svg" |
|
20 |
+ inkscape:version="0.92.2 5c3e80d, 2017-08-06"><sodipodi:namedview |
|
21 |
+ pagecolor="#ffffff" |
|
22 |
+ bordercolor="#666666" |
|
23 |
+ borderopacity="1" |
|
24 |
+ objecttolerance="10" |
|
25 |
+ gridtolerance="10" |
|
26 |
+ guidetolerance="10" |
|
27 |
+ inkscape:pageopacity="0" |
|
28 |
+ inkscape:pageshadow="2" |
|
29 |
+ inkscape:window-width="1918" |
|
30 |
+ inkscape:window-height="1198" |
|
31 |
+ id="namedview18" |
|
32 |
+ showgrid="false" |
|
33 |
+ inkscape:zoom="0.67285156" |
|
34 |
+ inkscape:cx="390.87373" |
|
35 |
+ inkscape:cy="321.77755" |
|
36 |
+ inkscape:window-x="1" |
|
37 |
+ inkscape:window-y="1" |
|
38 |
+ inkscape:window-maximized="0" |
|
39 |
+ inkscape:current-layer="Layer_1" /><metadata |
|
40 |
+ id="metadata76"><rdf:RDF><cc:Work |
|
41 |
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type |
|
42 |
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs |
|
43 |
+ id="defs74"><filter |
|
44 |
+ style="color-interpolation-filters:sRGB;" |
|
45 |
+ inkscape:label="Drop Shadow" |
|
46 |
+ id="filter4684"><feFlood |
|
47 |
+ flood-opacity="0.498039" |
|
48 |
+ flood-color="rgb(0,0,0)" |
|
49 |
+ result="flood" |
|
50 |
+ id="feFlood4674" /><feComposite |
|
51 |
+ in="flood" |
|
52 |
+ in2="SourceGraphic" |
|
53 |
+ operator="in" |
|
54 |
+ result="composite1" |
|
55 |
+ id="feComposite4676" /><feGaussianBlur |
|
56 |
+ in="composite1" |
|
57 |
+ stdDeviation="3" |
|
58 |
+ result="blur" |
|
59 |
+ id="feGaussianBlur4678" /><feOffset |
|
60 |
+ dx="16" |
|
61 |
+ dy="16" |
|
62 |
+ result="offset" |
|
63 |
+ id="feOffset4680" /><feComposite |
|
64 |
+ in="SourceGraphic" |
|
65 |
+ in2="offset" |
|
66 |
+ operator="over" |
|
67 |
+ result="fbSourceGraphic" |
|
68 |
+ id="feComposite4682" /><feColorMatrix |
|
69 |
+ result="fbSourceGraphicAlpha" |
|
70 |
+ in="fbSourceGraphic" |
|
71 |
+ values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0" |
|
72 |
+ id="feColorMatrix4686" /><feFlood |
|
73 |
+ id="feFlood4688" |
|
74 |
+ flood-opacity="0.498039" |
|
75 |
+ flood-color="rgb(0,0,0)" |
|
76 |
+ result="flood" |
|
77 |
+ in="fbSourceGraphic" /><feComposite |
|
78 |
+ in2="fbSourceGraphic" |
|
79 |
+ id="feComposite4690" |
|
80 |
+ in="flood" |
|
81 |
+ operator="in" |
|
82 |
+ result="composite1" /><feGaussianBlur |
|
83 |
+ id="feGaussianBlur4692" |
|
84 |
+ in="composite1" |
|
85 |
+ stdDeviation="3" |
|
86 |
+ result="blur" /><feOffset |
|
87 |
+ id="feOffset4694" |
|
88 |
+ dx="16" |
|
89 |
+ dy="16" |
|
90 |
+ result="offset" /><feComposite |
|
91 |
+ in2="offset" |
|
92 |
+ id="feComposite4696" |
|
93 |
+ in="fbSourceGraphic" |
|
94 |
+ operator="over" |
|
95 |
+ result="fbSourceGraphic" /><feColorMatrix |
|
96 |
+ result="fbSourceGraphicAlpha" |
|
97 |
+ in="fbSourceGraphic" |
|
98 |
+ values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0" |
|
99 |
+ id="feColorMatrix4698" /><feFlood |
|
100 |
+ id="feFlood4700" |
|
101 |
+ flood-opacity="0.498039" |
|
102 |
+ flood-color="rgb(0,0,0)" |
|
103 |
+ result="flood" |
|
104 |
+ in="fbSourceGraphic" /><feComposite |
|
105 |
+ in2="fbSourceGraphic" |
|
106 |
+ id="feComposite4702" |
|
107 |
+ in="flood" |
|
108 |
+ operator="in" |
|
109 |
+ result="composite1" /><feGaussianBlur |
|
110 |
+ id="feGaussianBlur4704" |
|
111 |
+ in="composite1" |
|
112 |
+ stdDeviation="3" |
|
113 |
+ result="blur" /><feOffset |
|
114 |
+ id="feOffset4706" |
|
115 |
+ dx="16" |
|
116 |
+ dy="16" |
|
117 |
+ result="offset" /><feComposite |
|
118 |
+ in2="offset" |
|
119 |
+ id="feComposite4708" |
|
120 |
+ in="fbSourceGraphic" |
|
121 |
+ operator="over" |
|
122 |
+ result="composite2" /></filter><inkscape:perspective |
|
123 |
+ id="perspective4636" |
|
124 |
+ inkscape:persp3d-origin="75.5 : 32.666667 : 1" |
|
125 |
+ inkscape:vp_z="151 : 49 : 1" |
|
126 |
+ inkscape:vp_y="0 : 1000 : 0" |
|
127 |
+ inkscape:vp_x="0 : 49 : 1" |
|
128 |
+ sodipodi:type="inkscape:persp3d" /><inkscape:perspective |
|
129 |
+ id="perspective4636-4" |
|
130 |
+ inkscape:persp3d-origin="75.5 : 32.666667 : 1" |
|
131 |
+ inkscape:vp_z="151 : 49 : 1" |
|
132 |
+ inkscape:vp_y="0 : 1000 : 0" |
|
133 |
+ inkscape:vp_x="0 : 49 : 1" |
|
134 |
+ sodipodi:type="inkscape:persp3d" /><filter |
|
135 |
+ y="-0.25" |
|
136 |
+ height="1.5" |
|
137 |
+ inkscape:menu-tooltip="Darkens the edge with an inner blur and adds a flexible glow" |
|
138 |
+ inkscape:menu="Shadows and Glows" |
|
139 |
+ inkscape:label="Dark and Glow" |
|
140 |
+ style="color-interpolation-filters:sRGB;" |
|
141 |
+ id="filter7493"><feGaussianBlur |
|
142 |
+ stdDeviation="5" |
|
143 |
+ result="result6" |
|
144 |
+ id="feGaussianBlur7483" /><feComposite |
|
145 |
+ result="result8" |
|
146 |
+ in="SourceGraphic" |
|
147 |
+ operator="atop" |
|
148 |
+ in2="result6" |
|
149 |
+ id="feComposite7485" /><feComposite |
|
150 |
+ result="result9" |
|
151 |
+ operator="over" |
|
152 |
+ in2="SourceAlpha" |
|
153 |
+ in="result8" |
|
154 |
+ id="feComposite7487" /><feColorMatrix |
|
155 |
+ values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 " |
|
156 |
+ result="result10" |
|
157 |
+ id="feColorMatrix7489" /><feBlend |
|
158 |
+ in="result10" |
|
159 |
+ mode="normal" |
|
160 |
+ in2="result6" |
|
161 |
+ id="feBlend7491" /></filter></defs><g |
|
162 |
+ inkscape:label="Calque 1" |
|
163 |
+ id="g7446" |
|
164 |
+ transform="matrix(5.5905096,0,0,6.8498347,89.916518,-6360.8651)" |
|
165 |
+ style="filter:url(#filter7493)"><g |
|
166 |
+ style="opacity:0.67801855" |
|
167 |
+ id="g7444"><path |
|
168 |
+ inkscape:connector-curvature="0" |
|
169 |
+ id="path7406" |
|
170 |
+ d="m 104.7944,978.86598 c 0,13.52888 -13.79395,24.49622 -30.80965,24.49622 -17.01571,0 -30.80966,-10.96734 -30.80966,-24.49622 0,-13.52887 13.79395,-24.4962 30.80966,-24.4962 17.0157,0 30.80965,10.96733 30.80965,24.4962 z" |
|
171 |
+ style="fill:#091119;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
172 |
+ inkscape:connector-curvature="0" |
|
173 |
+ id="path7408" |
|
174 |
+ d="m 103.42412,979.70978 c 0,13.43025 -13.23431,24.31762 -29.55965,24.31762 -16.32535,0 -29.55966,-10.88737 -29.55966,-24.31762 0,-13.43026 13.23431,-24.31763 29.55966,-24.31763 16.32534,0 29.55965,10.88737 29.55965,24.31763 z" |
|
175 |
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
176 |
+ inkscape:connector-curvature="0" |
|
177 |
+ id="path7410" |
|
178 |
+ d="m 106.05711,1009.9282 c 0,12.2736 -11.19345,22.2233 -25.00127,22.2233 -13.80783,0 -25.00128,-9.9497 -25.00128,-22.2233 0,-12.27363 11.19345,-22.22337 25.00128,-22.22337 13.80782,0 25.00127,9.94974 25.00127,22.22337 z" |
|
179 |
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
180 |
+ inkscape:connector-curvature="0" |
|
181 |
+ id="path7412" |
|
182 |
+ d="m 125.75508,992.7556 c 0,12.2736 -11.19345,22.2234 -25.00127,22.2234 -13.80783,0 -25.00128,-9.9498 -25.00128,-22.2234 0,-12.27362 11.19345,-22.22336 25.00128,-22.22336 13.80782,0 25.00127,9.94974 25.00127,22.22336 z" |
|
183 |
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
184 |
+ inkscape:connector-curvature="0" |
|
185 |
+ id="path7414" |
|
186 |
+ d="m 70.19668,999.82666 c 0,12.27364 -11.19345,22.22334 -25.00127,22.22334 -13.80783,0 -25.00128,-9.9497 -25.00128,-22.22334 0,-12.27362 11.19345,-22.22336 25.00128,-22.22336 13.80782,0 25.00127,9.94974 25.00127,22.22336 z" |
|
187 |
+ style="fill:#050a0f;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
188 |
+ inkscape:connector-curvature="0" |
|
189 |
+ id="path7416" |
|
190 |
+ d="m 72.61576,1000.9598 c 0,12.2736 -11.47328,22.2233 -25.62628,22.2233 -14.153,0 -25.62627,-9.9497 -25.62627,-22.2233 0,-12.27364 11.47327,-22.22338 25.62627,-22.22338 14.153,0 25.62628,9.94974 25.62628,22.22338 z" |
|
191 |
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
192 |
+ inkscape:connector-curvature="0" |
|
193 |
+ id="path7418" |
|
194 |
+ d="m 40.3972,1019.2721 c 0,9.9026 -8.93215,17.9302 -19.95051,17.9302 -11.01837,0 -19.95051,-8.0276 -19.95051,-17.9302 0,-9.9026 8.93214,-17.9302 19.95051,-17.9302 11.01836,0 19.95051,8.0276 19.95051,17.9302 z" |
|
195 |
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
196 |
+ inkscape:connector-curvature="0" |
|
197 |
+ id="path7420" |
|
198 |
+ d="m 40.95786,1019.699 c 0,9.3048 -8.77225,16.8479 -19.59337,16.8479 -10.82112,0 -19.59338,-7.5431 -19.59338,-16.8479 0,-9.3049 8.77226,-16.848 19.59338,-16.848 10.82112,0 19.59337,7.5431 19.59337,16.848 z" |
|
199 |
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
200 |
+ inkscape:connector-curvature="0" |
|
201 |
+ id="path7422" |
|
202 |
+ d="m 126.18719,994.88834 c 0,12.86536 -11.39333,23.29476 -25.44771,23.29476 -14.05438,0 -25.44771,-10.4294 -25.44771,-23.29476 0,-12.86535 11.39333,-23.29478 25.44771,-23.29478 14.05438,0 25.44771,10.42943 25.44771,23.29478 z" |
|
203 |
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
204 |
+ inkscape:connector-curvature="0" |
|
205 |
+ id="path7424" |
|
206 |
+ d="m 150.50382,1000.3317 c 0,12.2737 -11.19345,22.2234 -25.00127,22.2234 -13.80783,0 -25.00128,-9.9497 -25.00128,-22.2234 0,-12.27358 11.19345,-22.22332 25.00128,-22.22332 13.80782,0 25.00127,9.94974 25.00127,22.22332 z" |
|
207 |
+ style="fill:#030508;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
208 |
+ inkscape:connector-curvature="0" |
|
209 |
+ id="path7426" |
|
210 |
+ d="m 149.75861,1000.2455 c 0,11.5833 -11.2734,20.9733 -25.17984,20.9733 -13.90645,0 -25.17985,-9.39 -25.17985,-20.9733 0,-11.58327 11.2734,-20.97337 25.17985,-20.97337 13.90644,0 25.17984,9.3901 25.17984,20.97337 z" |
|
211 |
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
212 |
+ inkscape:connector-curvature="0" |
|
213 |
+ id="path7428" |
|
214 |
+ d="m 41.91242,1033.6668 c 0,6.5552 -5.201,11.8693 -11.61676,11.8693 -6.41575,0 -11.61675,-5.3141 -11.61675,-11.8693 0,-6.5553 5.201,-11.8693 11.61675,-11.8693 6.41576,0 11.61676,5.314 11.61676,11.8693 z" |
|
215 |
+ style="fill:#030609;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
216 |
+ inkscape:connector-curvature="0" |
|
217 |
+ id="path7430" |
|
218 |
+ d="m 42.26694,1032.9241 c 0,6.4566 -5.12105,11.6907 -11.43818,11.6907 -6.31714,0 -11.43819,-5.2341 -11.43819,-11.6907 0,-6.4566 5.12105,-11.6908 11.43819,-11.6908 6.31713,0 11.43818,5.2342 11.43818,11.6908 z" |
|
219 |
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
220 |
+ inkscape:connector-curvature="0" |
|
221 |
+ id="path7432" |
|
222 |
+ d="m 84.33882,1030.1312 c 0,12.2737 -11.19345,22.2234 -25.00127,22.2234 -13.80783,0 -25.00128,-9.9497 -25.00128,-22.2234 0,-12.2736 11.19345,-22.2233 25.00128,-22.2233 13.80782,0 25.00127,9.9497 25.00127,22.2233 z" |
|
223 |
+ style="fill:#050505;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
224 |
+ inkscape:connector-curvature="0" |
|
225 |
+ id="path7434" |
|
226 |
+ d="m 84.47542,1029.5542 c 0,12.0144 -10.93019,21.7539 -24.41325,21.7539 -13.48308,0 -24.41327,-9.7395 -24.41327,-21.7539 0,-12.0144 10.93019,-21.754 24.41327,-21.754 13.48306,0 24.41325,9.7396 24.41325,21.754 z" |
|
227 |
+ style="fill:#eeeeec;fill-opacity:0.99466672;fill-rule:nonzero;stroke:none" /><path |
|
228 |
+ inkscape:connector-curvature="0" |
|
229 |
+ id="path7436" |
|
230 |
+ d="m 139.39213,1020.0297 c 0,12.2736 -11.19345,22.2234 -25.00127,22.2234 -13.80783,0 -25.00128,-9.9498 -25.00128,-22.2234 0,-12.2736 11.19345,-22.22335 25.00128,-22.22335 13.80782,0 25.00127,9.94975 25.00127,22.22335 z" |
|
231 |
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
232 |
+ inkscape:connector-curvature="0" |
|
233 |
+ id="path7438" |
|
234 |
+ d="m 138.06218,1019.7544 c 0,11.8052 -11.21344,21.3752 -25.04592,21.3752 -13.83248,0 -25.04591,-9.57 -25.04591,-21.3752 0,-11.8051 11.21343,-21.37511 25.04591,-21.37511 13.83248,0 25.04592,9.57001 25.04592,21.37511 z" |
|
235 |
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
236 |
+ inkscape:connector-curvature="0" |
|
237 |
+ id="path7440" |
|
238 |
+ d="m 90.95831,1047.975 c -7.9716,1.3183 -15.50224,-3.8048 -16.82016,-11.4427 -1.31791,-7.638 4.07596,-14.8984 12.04756,-16.2166 7.9716,-1.3183 15.50224,3.8048 16.82016,11.4428 1.31792,7.6379 -4.07596,14.8983 -12.04756,16.2165 z" |
|
239 |
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path |
|
240 |
+ inkscape:connector-curvature="0" |
|
241 |
+ id="path7442" |
|
242 |
+ d="m 91.26841,1046.5778 c -7.83783,1.3182 -15.2421,-3.8049 -16.5379,-11.4428 -1.2958,-7.6379 4.00756,-14.8984 11.84539,-16.2166 7.83783,-1.3183 15.24211,3.8048 16.53791,11.4428 1.29579,7.6379 -4.00757,14.8983 -11.8454,16.2166 z" |
|
243 |
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g><g |
|
244 |
+ transform="matrix(0.71451596,0,0,0.71451596,145.64446,237.62552)" |
|
245 |
+ id="g69"><path |
|
246 |
+ inkscape:connector-curvature="0" |
|
247 |
+ style="fill:#ffffff;stroke:#000000;stroke-width:13.11448288;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" |
|
248 |
+ id="path65" |
|
249 |
+ d="m 465.388,355.317 c 28.549,0 142.254,0 142.254,0 0,0 -29.512,147.712 -29.562,148.266 -1.721,7.28 -7.158,18.114 -17.398,26.398 l -0.982,0.85 c -8.028,6.277 -19.036,11.183 -33.669,11.183 0,0 -80.374,0 -100.199,0 -3.174,14.971 -10.485,50.391 -14.807,71.465 26.174,0 93.87,0 93.87,0 132.024,0 158.075,-112.477 159.068,-117.022 0,0 37.714,-181.955 44.134,-213.259 -30.935,0 -206.868,0.369 -227.922,0.369 -3.022,14.97 -10.354,50.625 -14.787,71.75 z" /><path |
|
250 |
+ inkscape:connector-curvature="0" |
|
251 |
+ style="fill:#ffffff;stroke:#000000;stroke-width:13.11448288;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" |
|
252 |
+ id="path67" |
|
253 |
+ d="m 522.179,483.993 c 3.185,-14.909 10.383,-50.38 14.889,-71.628 -26.357,0 -94.505,0 -94.505,0 -2.038,0 -16.742,-1.004 -28.201,-10.312 -1.781,-1.505 -3.543,-3.153 -5.059,-5.119 -0.204,-0.175 -0.297,-0.257 -0.43,-0.554 -8.95,-11.396 -6.462,-26.204 -5.857,-29.419 0,0 21.136,-102.247 21.197,-102.697 1.73,-7.281 7.127,-17.777 17.131,-26.102 l 1.71,-1.403 c 8.162,-6.185 18.914,-10.721 33.332,-10.721 0,0 80.312,0 100.219,0 3.071,-15.216 10.424,-50.483 14.756,-71.516 -26.215,0 -93.87,0 -93.87,0 -132.086,0 -158.024,112.169 -159.161,116.838 l -21.002,101.98 c -0.102,0.543 -8.786,47.524 17.808,79.289 17.408,20.858 46.551,31.354 86.846,31.354 0.019,0.01 80.311,0.01 100.197,0.01 z" /></g></svg> |
|
0 | 254 |
\ No newline at end of file |
1 | 255 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,145 @@ |
1 |
+(in-package :mfa-tool) |
|
2 |
+ |
|
3 |
+(capi:define-interface mfa-tool () |
|
4 |
+ ((%default-account :initarg :default-account :reader default-account) |
|
5 |
+ (%signin-url :accessor signin-url)) |
|
6 |
+ (:panes |
|
7 |
+ (output-pane capi:collector-pane :reader output |
|
8 |
+ :visible-min-width (list :character 80) |
|
9 |
+ :visible-min-height (list :character 25)) |
|
10 |
+ (go-button capi:push-button :text "Go!" :callback 'go-on) |
|
11 |
+ (mfa-input capi:text-input-pane |
|
12 |
+ :title "MFA Token:" |
|
13 |
+ :title-position :left |
|
14 |
+ :max-characters 6 |
|
15 |
+ :callback 'go-on |
|
16 |
+ :title-args '(:visible-min-width (:character 11)) |
|
17 |
+ :reader mfa-input) |
|
18 |
+ (user-input capi:text-input-pane |
|
19 |
+ :title "Email:" |
|
20 |
+ :title-position :left |
|
21 |
+ :text (format nil "~a@cj.com" (uiop/os:getenv "USER")) |
|
22 |
+ :title-args '(:visible-min-width (:character 11)) |
|
23 |
+ :reader user-input) |
|
24 |
+ (account-selector capi:option-pane |
|
25 |
+ :print-function 'car |
|
26 |
+ :items *accounts* |
|
27 |
+ :selected-item (rassoc %default-account *accounts* |
|
28 |
+ :test 'equal) |
|
29 |
+ :selection-callback 'account-selected |
|
30 |
+ :callback-type :data |
|
31 |
+ :reader account-selector) |
|
32 |
+ (action-buttons capi:push-button-panel |
|
33 |
+ :items '(:|Open Web Console| |
|
34 |
+ :|Authorize iTerm|) |
|
35 |
+ :selection-callback 'execute-action |
|
36 |
+ :callback-type :data-interface) |
|
37 |
+ (listener-button capi:push-button |
|
38 |
+ :data :|Lisp REPL| |
|
39 |
+ :callback 'execute-action |
|
40 |
+ :callback-type :data-interface)) |
|
41 |
+ (:layouts |
|
42 |
+ (button-layout capi:row-layout |
|
43 |
+ '(nil |
|
44 |
+ go-button)) |
|
45 |
+ (data-layout capi:column-layout |
|
46 |
+ '(account-selector |
|
47 |
+ :separator |
|
48 |
+ user-input |
|
49 |
+ mfa-input |
|
50 |
+ button-layout)) |
|
51 |
+ (action-layout capi:row-layout |
|
52 |
+ `(listener-button |
|
53 |
+ nil |
|
54 |
+ action-buttons)) |
|
55 |
+ (right-layout capi:column-layout |
|
56 |
+ '(output-pane |
|
57 |
+ action-layout)) |
|
58 |
+ (main-layout capi:row-layout |
|
59 |
+ '(data-layout |
|
60 |
+ right-layout))) |
|
61 |
+ |
|
62 |
+ |
|
63 |
+ (:default-initargs |
|
64 |
+ :layout 'main-layout |
|
65 |
+ :title "CJ AWS Util")) |
|
66 |
+ |
|
67 |
+(defgeneric execute-action (action interface) |
|
68 |
+ (:method ((action (eql :|Open Web Console|)) (interface mfa-tool)) |
|
69 |
+ (open-url (signin-url interface))) |
|
70 |
+ (:method ((action (eql :|Authorize iTerm|)) (interface mfa-tool)) |
|
71 |
+ (uiop:run-program (format nil "osascript '~a'" |
|
72 |
+ (probe-file |
|
73 |
+ (merge-pathnames (make-pathname :name "AuthorizeShell" :type "scpt") |
|
74 |
+ (bundle-resource-root)))))) |
|
75 |
+ (:method ((action (eql :|Lisp REPL|)) (interface mfa-tool)) |
|
76 |
+ (capi:contain (make-instance 'capi:listener-pane) |
|
77 |
+ :best-width 1280 |
|
78 |
+ :best-height 800))) |
|
79 |
+ |
|
80 |
+(defun interface (&rest args &key default-account) |
|
81 |
+ (declare (ignore default-account)) |
|
82 |
+ (let ((interface (apply 'make-instance 'mfa-tool args))) |
|
83 |
+ (setf (capi:pane-initial-focus interface) |
|
84 |
+ (slot-value interface 'mfa-input)) |
|
85 |
+ (capi:set-button-panel-enabled-items (slot-value interface 'action-buttons) |
|
86 |
+ :set nil) |
|
87 |
+ (capi:set-application-interface (make-instance 'my-app-interface)) |
|
88 |
+ (capi:display interface))) |
|
89 |
+ |
|
90 |
+(eval-when (:compile-toplevel :load-toplevel :execute) |
|
91 |
+ (defun debugging (condition fun) |
|
92 |
+ (declare (ignore fun)) |
|
93 |
+ (let ((*print-readably* nil) |
|
94 |
+ (out (make-instance 'capi:collector-pane))) |
|
95 |
+ (princ condition (capi:collector-pane-stream out)) |
|
96 |
+ (prin1 (mapcar 'restart-name |
|
97 |
+ (compute-restarts condition) ) |
|
98 |
+ (capi:collector-pane-stream out)) |
|
99 |
+ (capi:contain out) |
|
100 |
+ (abort)))) |
|
101 |
+ |
|
102 |
+(capi:define-interface my-app-interface (capi:cocoa-default-application-interface) |
|
103 |
+ () |
|
104 |
+ (:menus |
|
105 |
+ (edit-menu |
|
106 |
+ "Edit" |
|
107 |
+ (undo-component standard-edit-component selection-component) |
|
108 |
+ :callback-type :interface) |
|
109 |
+ (window-menu |
|
110 |
+ "Window" |
|
111 |
+ (("Close Window" |
|
112 |
+ :accelerator "accelerator-w" |
|
113 |
+ :enabled-function 'close-active-screen-enabled |
|
114 |
+ :callback 'close-active-screen |
|
115 |
+ :callback-type nil))) |
|
116 |
+ (standard-edit-component |
|
117 |
+ :component |
|
118 |
+ (("Cut" :callback 'capi:active-pane-cut |
|
119 |
+ :enabled-function 'capi:active-pane-cut-p) |
|
120 |
+ ("Copy" :callback 'capi:active-pane-copy |
|
121 |
+ :enabled-function 'capi:active-pane-copy-p) |
|
122 |
+ ("Paste" :callback 'capi:active-pane-paste |
|
123 |
+ :enabled-function 'capi:active-pane-paste-p))) |
|
124 |
+ |
|
125 |
+ (selection-component |
|
126 |
+ :component |
|
127 |
+ (("Select All" :callback 'capi:active-pane-select-all))) |
|
128 |
+ |
|
129 |
+ (undo-component |
|
130 |
+ :component |
|
131 |
+ (("Undo" :data :undo |
|
132 |
+ :enabled-function 'capi:active-pane-undo-p |
|
133 |
+ :callback 'capi:active-pane-undo)))) |
|
134 |
+ |
|
135 |
+ (:menu-bar edit-menu window-menu)) |
|
136 |
+ |
|
137 |
+(defun main () |
|
138 |
+ (setf *debugger-hook* 'debugging |
|
139 |
+ *print-readably* nil |
|
140 |
+ *accounts* (reprocess-accounts (load-accounts))) |
|
141 |
+ (ubiquitous:restore :cj.mfa-tool) |
|
142 |
+ (let ((*debugger-hook* 'debugging)) |
|
143 |
+ (setf aws:*session* (aws:make-session)) |
|
144 |
+ (interface :default-account |
|
145 |
+ (ubiquitous:value :default-account)))) |
0 | 146 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,73 @@ |
1 |
+(in-package :mfa-tool) |
|
2 |
+ |
|
3 |
+(defvar *accounts* ()) |
|
4 |
+ |
|
5 |
+(defun session-name () |
|
6 |
+ (format nil "bootstrap~d" (+ 5000 (random 5000)))) |
|
7 |
+ |
|
8 |
+(defparameter *user_management_account_id* 597974043991) |
|
9 |
+ |
|
10 |
+ |
|
11 |
+(defun do-auth (user role token account) |
|
12 |
+ (let ((mfa-serial-number |
|
13 |
+ (format nil "arn:aws:iam::~a:mfa/~a" |
|
14 |
+ *user_management_account_id* |
|
15 |
+ user)) |
|
16 |
+ (role-arn |
|
17 |
+ (format nil "arn:aws:iam::~a:role/cjorganization/~a" |
|
18 |
+ account |
|
19 |
+ role))) |
|
20 |
+ (aws/sts:assume-role :role-arn role-arn |
|
21 |
+ :role-session-name (session-name) |
|
22 |
+ :serial-number mfa-serial-number |
|
23 |
+ :duration-seconds #.(* 12 60 60) |
|
24 |
+ :token-code token))) |
|
25 |
+ |
|
26 |
+(defun get-url (params) |
|
27 |
+ (format nil "https://signin.aws.amazon.com/federation?Action=getSigninToken&Session=~a" |
|
28 |
+ (quri.encode:url-encode (with-output-to-string (s) |
|
29 |
+ (yason:encode params s)) |
|
30 |
+ :space-to-plus t))) |
|
31 |
+ |
|
32 |
+(cells:defmodel |
|
33 |
+ sts-result-handler () |
|
34 |
+ ((api-result :initarg :api-result :accessor api-result :initform (cells:c-in nil)) |
|
35 |
+ (credentials :reader credentials |
|
36 |
+ :initform (cells:c? (serapeum:assocdr "Credentials" (^api-result) |
|
37 |
+ :test 'equal))) |
|
38 |
+ (session-id :reader session-id |
|
39 |
+ :initform (cells:c? (serapeum:assocadr "AccessKeyId" (^credentials) |
|
40 |
+ :test 'equal))) |
|
41 |
+ (session-key :reader session-key |
|
42 |
+ :initform (cells:c? (serapeum:assocadr "SecretAccessKey" (^credentials) |
|
43 |
+ :test 'equal))) |
|
44 |
+ (session-token :reader session-token |
|
45 |
+ :initform (cells:c? (serapeum:assocadr "SessionToken" (^credentials) |
|
46 |
+ :test 'equal))) |
|
47 |
+ (url-params :reader url-params |
|
48 |
+ :initform (cells:c? (fw.lu:alist-string-hash-table |
|
49 |
+ `(("sessionId" . ,(^session-id)) |
|
50 |
+ ("sessionKey" . ,(^session-key)) |
|
51 |
+ ("sessionToken" . ,(^session-token)))) )) |
|
52 |
+ (url :reader url |
|
53 |
+ :initform (cells:c? (get-url (^url-params)))))) |
|
54 |
+ |
|
55 |
+(defun url-from-signin-token (signin-token) |
|
56 |
+ (format nil "https://signin.aws.amazon.com/federation?Action=login&Destination=https%3A%2F%2Fconsole.aws.amazon.com&SigninToken=~a" |
|
57 |
+ signin-token)) |
|
58 |
+ |
|
59 |
+(defun run-process (account user token) |
|
60 |
+ (let* ((api-result (cells:c-in (do-auth user "CJDeveloperAccessRole" token account))) |
|
61 |
+ (parser (make-instance 'sts-result-handler :api-result api-result)) |
|
62 |
+ (federation-url (url parser)) |
|
63 |
+ (signin-token (gethash "SigninToken" |
|
64 |
+ (yason:parse |
|
65 |
+ (dexador:get federation-url))))) |
|
66 |
+ (values signin-token |
|
67 |
+ parser))) |
|
68 |
+ |
|
69 |
+(defun open-url (url) |
|
70 |
+ (capi:contain (make-instance 'capi:browser-pane |
|
71 |
+ :url url) |
|
72 |
+ :best-width 1280 |
|
73 |
+ :best-height 800)) |
0 | 74 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,82 @@ |
1 |
+(in-package :mfa-tool) |
|
2 |
+ |
|
3 |
+(defun account-selected (account) |
|
4 |
+ (format t "~s" account) |
|
5 |
+ (setf (ubiquitous:value :default-account) |
|
6 |
+ (cdr account))) |
|
7 |
+ |
|
8 |
+(defparameter *developer-p* (equal "elangley" (uiop/os:getenv "USER"))) |
|
9 |
+ |
|
10 |
+(defun bundle-resource-root () |
|
11 |
+ (make-pathname :directory |
|
12 |
+ (pathname-directory |
|
13 |
+ (objc:invoke-into 'string |
|
14 |
+ (objc:invoke "NSBundle" "mainBundle") |
|
15 |
+ "pathForResource:ofType:" "app" "icns")))) |
|
16 |
+ |
|
17 |
+(defun clear-cookies () |
|
18 |
+ (let ((cookie-storage (objc:invoke "NSHTTPCookieStorage" "sharedHTTPCookieStorage"))) |
|
19 |
+ (map nil |
|
20 |
+ (lambda (cookie) |
|
21 |
+ (objc:invoke cookie-storage "deleteCookie:" cookie)) |
|
22 |
+ (objc:invoke-into 'array cookie-storage "cookies")))) |
|
23 |
+ |
|
24 |
+(defun go-on (_ interface) |
|
25 |
+ (declare (ignore _)) |
|
26 |
+ (let ((token (capi:text-input-pane-text (mfa-input interface))) |
|
27 |
+ (user-name (capi:text-input-pane-text (user-input interface))) |
|
28 |
+ (account (cdr (capi:choice-selected-item (account-selector interface))))) |
|
29 |
+ (clear-cookies) |
|
30 |
+ (multiple-value-bind (signin-token creds) (run-process account user-name token) |
|
31 |
+ (with-open-file (stream (make-pathname :name "" |
|
32 |
+ :type "cj-aws" |
|
33 |
+ :defaults (user-homedir-pathname)) |
|
34 |
+ :direction :output |
|
35 |
+ :if-exists :rename |
|
36 |
+ :if-does-not-exist :create) |
|
37 |
+ (format (make-broadcast-stream stream |
|
38 |
+ (capi:collector-pane-stream (output interface))) |
|
39 |
+ "export AWS_ACCESS_KEY_ID='~a'~%export AWS_SECRET_ACCESS_KEY='~a'~%export AWS_SESSION_TOKEN='~a'~%" |
|
40 |
+ (session-id creds) |
|
41 |
+ (session-key creds) |
|
42 |
+ (session-token creds))) |
|
43 |
+ (capi:set-button-panel-enabled-items (slot-value interface 'action-buttons) |
|
44 |
+ :set t) |
|
45 |
+ (setf (signin-url interface) |
|
46 |
+ (url-from-signin-token signin-token))))) |
|
47 |
+ |
|
48 |
+(defun close-active-screen () |
|
49 |
+ (let ((active-interface |
|
50 |
+ (capi:screen-active-interface |
|
51 |
+ (capi:convert-to-screen)))) |
|
52 |
+ (unless (typep active-interface 'mfa-tool) |
|
53 |
+ (capi:destroy active-interface)))) |
|
54 |
+ |
|
55 |
+ |
|
56 |
+(defun close-active-screen-enabled () |
|
57 |
+ (let ((active-interface |
|
58 |
+ (capi:screen-active-interface |
|
59 |
+ (capi:convert-to-screen)))) |
|
60 |
+ (typep active-interface '(not mfa-tool)))) |
|
61 |
+ |
|
62 |
+(defun load-accounts () |
|
63 |
+ (yason:parse |
|
64 |
+ (alexandria:read-file-into-string |
|
65 |
+ (merge-pathnames (make-pathname :name "accounts" |
|
66 |
+ :type "json") |
|
67 |
+ (bundle-resource-root))))) |
|
68 |
+ |
|
69 |
+(defun reprocess-accounts (accounts) |
|
70 |
+ (let ((accounts (gethash "Accounts" accounts)) |
|
71 |
+ (result ())) |
|
72 |
+ (mapc (lambda (account) |
|
73 |
+ (push (cons (format nil "~a (~a)" |
|
74 |
+ (gethash "Name" account) |
|
75 |
+ (gethash "Type" account)) |
|
76 |
+ (gethash "Id" account)) |
|
77 |
+ result)) |
|
78 |
+ accounts) |
|
79 |
+ (coerce (sort result 'string-lessp |
|
80 |
+ :key 'car) |
|
81 |
+ 'list))) |
|
82 |
+ |