cloud-formation.json 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. {
  2. "AWSTemplateFormatVersion": "2010-09-09",
  3. "Metadata": {
  4. "AWS::CloudFormation::Designer": {
  5. "ee78c12d-0d1e-4ca0-8fa9-ba02f49d071c": {
  6. "size": {
  7. "width": 60,
  8. "height": 60
  9. },
  10. "position": {
  11. "x": 30,
  12. "y": 60
  13. },
  14. "z": 0,
  15. "embeds": []
  16. },
  17. "a52902b8-f027-45a8-9151-3e56ced5fb42": {
  18. "size": {
  19. "width": 60,
  20. "height": 60
  21. },
  22. "position": {
  23. "x": 30,
  24. "y": 140
  25. },
  26. "z": 0,
  27. "embeds": []
  28. },
  29. "674a64fc-3703-4222-91b9-4878490489e2": {
  30. "size": {
  31. "width": 60,
  32. "height": 60
  33. },
  34. "position": {
  35. "x": 250,
  36. "y": 100
  37. },
  38. "z": 0,
  39. "embeds": [],
  40. "isassociatedwith": [
  41. "5c314e8e-535b-4b09-8bb7-c089794a3829"
  42. ]
  43. },
  44. "5c314e8e-535b-4b09-8bb7-c089794a3829": {
  45. "size": {
  46. "width": 60,
  47. "height": 60
  48. },
  49. "position": {
  50. "x": 250,
  51. "y": 210
  52. },
  53. "z": 0,
  54. "embeds": []
  55. },
  56. "3da9a376-afc1-4b37-add1-9cf0df20b0a0": {
  57. "size": {
  58. "width": 60,
  59. "height": 60
  60. },
  61. "position": {
  62. "x": 360,
  63. "y": 100
  64. },
  65. "z": 0,
  66. "embeds": []
  67. },
  68. "7fd11cc7-5574-44f3-99df-877b6f0f2a74": {
  69. "size": {
  70. "width": 60,
  71. "height": 60
  72. },
  73. "position": {
  74. "x": 130,
  75. "y": 60
  76. },
  77. "z": 0,
  78. "embeds": [],
  79. "isassociatedwith": [
  80. "ee78c12d-0d1e-4ca0-8fa9-ba02f49d071c"
  81. ]
  82. },
  83. "1d8a8e19-2661-44d4-99c0-4a2c88c8557d": {
  84. "size": {
  85. "width": 60,
  86. "height": 60
  87. },
  88. "position": {
  89. "x": 130,
  90. "y": 140
  91. },
  92. "z": 0,
  93. "embeds": [],
  94. "isassociatedwith": [
  95. "a52902b8-f027-45a8-9151-3e56ced5fb42"
  96. ]
  97. },
  98. "e29c9a81-85ad-4511-ab1e-018fe50f1573": {
  99. "size": {
  100. "width": 60,
  101. "height": 60
  102. },
  103. "position": {
  104. "x": 30,
  105. "y": 220
  106. },
  107. "z": 0,
  108. "embeds": []
  109. },
  110. "1388662c-85e1-4f6e-9b80-0f1888a6e07d": {
  111. "size": {
  112. "width": 60,
  113. "height": 60
  114. },
  115. "position": {
  116. "x": 130,
  117. "y": 220
  118. },
  119. "z": 0,
  120. "embeds": [],
  121. "isassociatedwith": [
  122. "e29c9a81-85ad-4511-ab1e-018fe50f1573"
  123. ]
  124. },
  125. "236600ec-46ca-4770-8d7c-61532a6d8c27": {
  126. "size": {
  127. "width": 60,
  128. "height": 60
  129. },
  130. "position": {
  131. "x": 30,
  132. "y": 300
  133. },
  134. "z": 0,
  135. "embeds": []
  136. },
  137. "454a6298-2f35-48d7-8cd5-3152d78a585b": {
  138. "size": {
  139. "width": 60,
  140. "height": 60
  141. },
  142. "position": {
  143. "x": 130,
  144. "y": 300
  145. },
  146. "z": 0,
  147. "embeds": []
  148. }
  149. }
  150. },
  151. "Resources": {
  152. "Blobs": {
  153. "Type": "AWS::S3::Bucket",
  154. "Properties": {
  155. "BucketName": {
  156. "Fn::Join": [
  157. "-",
  158. [
  159. {
  160. "Ref": "OverleafEditorBucketPrefix"
  161. },
  162. "blobs"
  163. ]
  164. ]
  165. },
  166. "VersioningConfiguration": {
  167. "Status": "Enabled"
  168. },
  169. "LifecycleConfiguration": {
  170. "Rules": [
  171. {
  172. "NoncurrentVersionExpirationInDays": 90,
  173. "Status": "Enabled"
  174. }
  175. ]
  176. },
  177. "BucketEncryption": {
  178. "ServerSideEncryptionConfiguration": [
  179. {
  180. "ServerSideEncryptionByDefault": {
  181. "SSEAlgorithm": "AES256"
  182. }
  183. }
  184. ]
  185. }
  186. },
  187. "Metadata": {
  188. "AWS::CloudFormation::Designer": {
  189. "id": "ee78c12d-0d1e-4ca0-8fa9-ba02f49d071c"
  190. }
  191. }
  192. },
  193. "Chunks": {
  194. "Type": "AWS::S3::Bucket",
  195. "Properties": {
  196. "BucketName": {
  197. "Fn::Join": [
  198. "-",
  199. [
  200. {
  201. "Ref": "OverleafEditorBucketPrefix"
  202. },
  203. "chunks"
  204. ]
  205. ]
  206. },
  207. "VersioningConfiguration": {
  208. "Status": "Enabled"
  209. },
  210. "LifecycleConfiguration": {
  211. "Rules": [
  212. {
  213. "NoncurrentVersionExpirationInDays": 80,
  214. "Status": "Enabled"
  215. }
  216. ]
  217. },
  218. "BucketEncryption": {
  219. "ServerSideEncryptionConfiguration": [
  220. {
  221. "ServerSideEncryptionByDefault": {
  222. "SSEAlgorithm": "AES256"
  223. }
  224. }
  225. ]
  226. }
  227. },
  228. "Metadata": {
  229. "AWS::CloudFormation::Designer": {
  230. "id": "a52902b8-f027-45a8-9151-3e56ced5fb42"
  231. }
  232. }
  233. },
  234. "APIUser": {
  235. "Type": "AWS::IAM::User",
  236. "Properties": {
  237. "Groups": [
  238. {
  239. "Ref": "APIGroup"
  240. }
  241. ]
  242. },
  243. "Metadata": {
  244. "AWS::CloudFormation::Designer": {
  245. "id": "674a64fc-3703-4222-91b9-4878490489e2"
  246. }
  247. }
  248. },
  249. "APIGroup": {
  250. "Type": "AWS::IAM::Group",
  251. "Properties": {},
  252. "Metadata": {
  253. "AWS::CloudFormation::Designer": {
  254. "id": "5c314e8e-535b-4b09-8bb7-c089794a3829"
  255. }
  256. }
  257. },
  258. "APIUserAccessKey": {
  259. "Type": "AWS::IAM::AccessKey",
  260. "Properties": {
  261. "UserName": {
  262. "Ref": "APIUser"
  263. }
  264. },
  265. "Metadata": {
  266. "AWS::CloudFormation::Designer": {
  267. "id": "3da9a376-afc1-4b37-add1-9cf0df20b0a0"
  268. }
  269. }
  270. },
  271. "BlobsPolicy": {
  272. "Type": "AWS::S3::BucketPolicy",
  273. "Properties": {
  274. "Bucket": {
  275. "Ref": "Blobs"
  276. },
  277. "PolicyDocument": {
  278. "Id": "BlobsPolicy",
  279. "Version": "2012-10-17",
  280. "Statement": [
  281. {
  282. "Sid": "BlobsPolicyAPIUser",
  283. "Action": [
  284. "s3:GetObject",
  285. "s3:PutObject"
  286. ],
  287. "Effect": "Allow",
  288. "Resource": {
  289. "Fn::Join": [
  290. "",
  291. [
  292. "arn:aws:s3:::",
  293. {
  294. "Ref": "Blobs"
  295. },
  296. "/*"
  297. ]
  298. ]
  299. },
  300. "Principal": {
  301. "AWS": {
  302. "Fn::GetAtt": [
  303. "APIUser",
  304. "Arn"
  305. ]
  306. }
  307. }
  308. }
  309. ]
  310. }
  311. },
  312. "Metadata": {
  313. "AWS::CloudFormation::Designer": {
  314. "id": "7fd11cc7-5574-44f3-99df-877b6f0f2a74"
  315. }
  316. }
  317. },
  318. "ChunksPolicy": {
  319. "Type": "AWS::S3::BucketPolicy",
  320. "Properties": {
  321. "Bucket": {
  322. "Ref": "Chunks"
  323. },
  324. "PolicyDocument": {
  325. "Id": "ChunksPolicy",
  326. "Version": "2012-10-17",
  327. "Statement": [
  328. {
  329. "Sid": "ChunksPolicyAPIUser",
  330. "Action": [
  331. "s3:GetObject",
  332. "s3:PutObject",
  333. "s3:DeleteObject"
  334. ],
  335. "Effect": "Allow",
  336. "Resource": {
  337. "Fn::Join": [
  338. "",
  339. [
  340. "arn:aws:s3:::",
  341. {
  342. "Ref": "Chunks"
  343. },
  344. "/*"
  345. ]
  346. ]
  347. },
  348. "Principal": {
  349. "AWS": {
  350. "Fn::GetAtt": [
  351. "APIUser",
  352. "Arn"
  353. ]
  354. }
  355. }
  356. }
  357. ]
  358. }
  359. },
  360. "Metadata": {
  361. "AWS::CloudFormation::Designer": {
  362. "id": "1d8a8e19-2661-44d4-99c0-4a2c88c8557d"
  363. }
  364. }
  365. },
  366. "Zips": {
  367. "Type": "AWS::S3::Bucket",
  368. "Properties": {
  369. "BucketName": {
  370. "Fn::Join": [
  371. "-",
  372. [
  373. {
  374. "Ref": "OverleafEditorBucketPrefix"
  375. },
  376. "zips"
  377. ]
  378. ]
  379. },
  380. "BucketEncryption": {
  381. "ServerSideEncryptionConfiguration": [
  382. {
  383. "ServerSideEncryptionByDefault": {
  384. "SSEAlgorithm": "AES256"
  385. }
  386. }
  387. ]
  388. },
  389. "LifecycleConfiguration": {
  390. "Rules": [
  391. {
  392. "ExpirationInDays": 1,
  393. "Status": "Enabled"
  394. }
  395. ]
  396. },
  397. "PublicAccessBlockConfiguration": {
  398. "BlockPublicAcls": true,
  399. "BlockPublicPolicy": true,
  400. "IgnorePublicAcls": true,
  401. "RestrictPublicBuckets": true
  402. }
  403. },
  404. "Metadata": {
  405. "AWS::CloudFormation::Designer": {
  406. "id": "e29c9a81-85ad-4511-ab1e-018fe50f1573"
  407. }
  408. }
  409. },
  410. "ZipsPolicy": {
  411. "Type": "AWS::S3::BucketPolicy",
  412. "Properties": {
  413. "Bucket": {
  414. "Ref": "Zips"
  415. },
  416. "PolicyDocument": {
  417. "Id": "ZipsPolicy",
  418. "Version": "2012-10-17",
  419. "Statement": [
  420. {
  421. "Sid": "ZipsPolicyAPIUser",
  422. "Action": [
  423. "s3:GetObject",
  424. "s3:PutObject"
  425. ],
  426. "Effect": "Allow",
  427. "Resource": {
  428. "Fn::Join": [
  429. "",
  430. [
  431. "arn:aws:s3:::",
  432. {
  433. "Ref": "Zips"
  434. },
  435. "/*"
  436. ]
  437. ]
  438. },
  439. "Principal": {
  440. "AWS": {
  441. "Fn::GetAtt": [
  442. "APIUser",
  443. "Arn"
  444. ]
  445. }
  446. }
  447. }
  448. ]
  449. }
  450. },
  451. "Metadata": {
  452. "AWS::CloudFormation::Designer": {
  453. "id": "1388662c-85e1-4f6e-9b80-0f1888a6e07d"
  454. }
  455. }
  456. },
  457. "Analytics": {
  458. "Type": "AWS::S3::Bucket",
  459. "Properties": {
  460. "BucketName": {
  461. "Fn::Join": [
  462. "-",
  463. [
  464. {
  465. "Ref": "OverleafEditorBucketPrefix"
  466. },
  467. "analytics"
  468. ]
  469. ]
  470. }
  471. },
  472. "Metadata": {
  473. "AWS::CloudFormation::Designer": {
  474. "id": "236600ec-46ca-4770-8d7c-61532a6d8c27"
  475. }
  476. }
  477. },
  478. "AnalyticsPolicy": {
  479. "Type": "AWS::S3::BucketPolicy",
  480. "Properties": {
  481. "Bucket": {
  482. "Ref": "Analytics"
  483. },
  484. "PolicyDocument": {
  485. "Id": "AnalyticsPolicy",
  486. "Version": "2012-10-17",
  487. "Statement": [
  488. {
  489. "Sid": "AnalyticsPolicyAPIUser",
  490. "Action": [
  491. "s3:GetObject",
  492. "s3:PutObject",
  493. "s3:DeleteObject"
  494. ],
  495. "Effect": "Allow",
  496. "Resource": {
  497. "Fn::Join": [
  498. "",
  499. [
  500. "arn:aws:s3:::",
  501. {
  502. "Ref": "Analytics"
  503. },
  504. "/*"
  505. ]
  506. ]
  507. },
  508. "Principal": {
  509. "AWS": {
  510. "Fn::GetAtt": [
  511. "APIUser",
  512. "Arn"
  513. ]
  514. }
  515. }
  516. },
  517. {
  518. "Sid": "AnalyticsPolicyAPIUserBucketPerms",
  519. "Action": "s3:ListBucket",
  520. "Effect": "Allow",
  521. "Resource": {
  522. "Fn::Join": [
  523. "",
  524. [
  525. "arn:aws:s3:::",
  526. {
  527. "Ref": "Analytics"
  528. }
  529. ]
  530. ]
  531. },
  532. "Principal": {
  533. "AWS": {
  534. "Fn::GetAtt": [
  535. "APIUser",
  536. "Arn"
  537. ]
  538. }
  539. }
  540. }
  541. ]
  542. }
  543. },
  544. "Metadata": {
  545. "AWS::CloudFormation::Designer": {
  546. "id": "454a6298-2f35-48d7-8cd5-3152d78a585b"
  547. }
  548. }
  549. }
  550. },
  551. "Parameters": {
  552. "OverleafEditorBucketPrefix": {
  553. "Description": "Prefix for the S3 bucket names (e.g. production-overleaf-editor or staging-overleaf-editor)",
  554. "Type": "String"
  555. }
  556. },
  557. "Outputs": {
  558. "APIUserAccessKey": {
  559. "Value": {
  560. "Ref": "APIUserAccessKey"
  561. }
  562. },
  563. "APIUserSecretKey": {
  564. "Value": {
  565. "Fn::GetAtt": [
  566. "APIUserAccessKey",
  567. "SecretAccessKey"
  568. ]
  569. }
  570. }
  571. }
  572. }