Compare commits
850 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38bc336771 | ||
|
|
276f6f9fb1 | ||
|
|
2386c71c4f | ||
|
|
21c52db66b | ||
|
|
13cfa02f80 | ||
|
|
eedfbe3e7a | ||
|
|
fe03eb4436 | ||
|
|
d8e45d5c3f | ||
|
|
12e9fb5eeb | ||
|
|
957ffaabae | ||
|
|
cb76e5a23c | ||
|
|
b17cc563ff | ||
|
|
06a0b12efb | ||
|
|
d5bd5ebb7d | ||
|
|
0a9a1c26db | ||
|
|
83bfd8a2d4 | ||
|
|
e5d2c0c700 | ||
|
|
590a5669d6 | ||
|
|
e042740f67 | ||
|
|
dab2ecaa6b | ||
|
|
f9f4133b48 | ||
|
|
33dd21897d | ||
|
|
cb2ef23a29 | ||
|
|
e70e01196f | ||
|
|
f70b9e6eb4 | ||
|
|
d186c69473 | ||
|
|
4d817c48a8 | ||
|
|
c13cab792b | ||
|
|
80aa463aa2 | ||
|
|
bd28b17ad9 | ||
|
|
223119e303 | ||
|
|
7c45cb45ae | ||
|
|
ac11c6729b | ||
|
|
1677654dea | ||
|
|
bc5a7a961b | ||
|
|
c10462223d | ||
|
|
54a9f412e8 | ||
|
|
5a107c58bb | ||
|
|
8f091e7548 | ||
|
|
8cdc7b18c7 | ||
|
|
9f2e87e9fb | ||
|
|
e119458048 | ||
|
|
c2983faf1d | ||
|
|
a09855207e | ||
|
|
1e1859ba6f | ||
|
|
a3937e48a8 | ||
|
|
d2aa53a2ec | ||
|
|
b0bdeea60f | ||
|
|
465e64b9ac | ||
|
|
fc53b28997 | ||
|
|
72e701a4b5 | ||
|
|
2298d5356d | ||
|
|
54137be92b | ||
|
|
7ffb12268d | ||
|
|
790fff460a | ||
|
|
9055dbafe3 | ||
|
|
4454d9115e | ||
|
|
0d74dec446 | ||
|
|
0313dba7b4 | ||
|
|
3fafac75ef | ||
|
|
6b24b46f3d | ||
|
|
474e39a4c9 | ||
|
|
e652298b6a | ||
|
|
9340ae43f3 | ||
|
|
552024c53e | ||
|
|
3aba71ad2f | ||
|
|
ade511df28 | ||
|
|
fc650214d4 | ||
|
|
8266fd0c6f | ||
|
|
f4308032c3 | ||
|
|
1e1f445ade | ||
|
|
d41b0332ac | ||
|
|
7258466572 | ||
|
|
76db92ea14 | ||
|
|
ad3cd66e08 | ||
|
|
22f8855ad7 | ||
|
|
36e095c830 | ||
|
|
887cac1264 | ||
|
|
13059e0568 | ||
|
|
9e8023d716 | ||
|
|
c54ba5fd8c | ||
|
|
db80e063d4 | ||
|
|
b6aa12706a | ||
|
|
c1caf6717d | ||
|
|
513fd9f532 | ||
|
|
bf77f817cb | ||
|
|
e0bfef2ece | ||
|
|
4a87f908a8 | ||
|
|
16d95e5155 | ||
|
|
1797b54259 | ||
|
|
f289c8fb2e | ||
|
|
e4ad881a69 | ||
|
|
138bca38e7 | ||
|
|
44f7af3580 | ||
|
|
2d832bca15 | ||
|
|
efa75a62e3 | ||
|
|
5763bca317 | ||
|
|
c335334402 | ||
|
|
5bf3f70717 | ||
|
|
92c8a440ea | ||
|
|
b92d8a014c | ||
|
|
aced44f051 | ||
|
|
49c9d2b077 | ||
|
|
61beacf085 | ||
|
|
02f432238e | ||
|
|
864d178e01 | ||
|
|
78f0b823a9 | ||
|
|
26cdc7a0ee | ||
|
|
5e773f1eee | ||
|
|
4a7ac7df22 | ||
|
|
5250670d5d | ||
|
|
de4a825db8 | ||
|
|
c256419144 | ||
|
|
7bdca0420e | ||
|
|
3aa1fbced9 | ||
|
|
dbbb70027a | ||
|
|
b4e78d28f8 | ||
|
|
e3d4e38a59 | ||
|
|
386f558eae | ||
|
|
e08424d3a3 | ||
|
|
03ad403e7a | ||
|
|
4a674aae99 | ||
|
|
8ee3744027 | ||
|
|
965327e801 | ||
|
|
f82ea43324 | ||
|
|
a5c63845b4 | ||
|
|
034faa72cf | ||
|
|
9bcd617964 | ||
|
|
0db975dc7b | ||
|
|
a51fa7703b | ||
|
|
69fad0009d | ||
|
|
e721251936 | ||
|
|
2fe767e3e5 | ||
|
|
6328ef4444 | ||
|
|
50b8e084e7 | ||
|
|
3d88544feb | ||
|
|
62e602c32e | ||
|
|
47a82560ea | ||
|
|
f7bbcc98b3 | ||
|
|
98a587aa15 | ||
|
|
d2e34c42fd | ||
|
|
605b07901e | ||
|
|
18f02fac68 | ||
|
|
28ea37f367 | ||
|
|
65a737bb58 | ||
|
|
7423cd2f93 | ||
|
|
babd026351 | ||
|
|
dd6e5a9029 | ||
|
|
02519a4429 | ||
|
|
6575121b7a | ||
|
|
5b66368f0d | ||
|
|
971c6720e4 | ||
|
|
3afccc279f | ||
|
|
8f015d0672 | ||
|
|
f33b96861c | ||
|
|
9832ce2ff9 | ||
|
|
490cbbaa48 | ||
|
|
d1c91093e2 | ||
|
|
66fe101ccd | ||
|
|
7ab8c6b154 | ||
|
|
73017b14c3 | ||
|
|
f55495cd6a | ||
|
|
e97146b5a3 | ||
|
|
58f056c76d | ||
|
|
338bbc7a1f | ||
|
|
4ba54738a9 | ||
|
|
235fd2adc4 | ||
|
|
b15d518c94 | ||
|
|
021e1c122c | ||
|
|
014b0dd6f6 | ||
|
|
f9f68f9b86 | ||
|
|
11a8ba131a | ||
|
|
858de64f8e | ||
|
|
676e60afb7 | ||
|
|
b1968f3f8b | ||
|
|
d2d077afaa | ||
|
|
7097ca401d | ||
|
|
73e9a1eb9e | ||
|
|
0439d455fb | ||
|
|
d57f665a78 | ||
|
|
859c731a13 | ||
|
|
2e7613ddec | ||
|
|
57e9436783 | ||
|
|
2f153fda2e | ||
|
|
cbcb5905a3 | ||
|
|
6a2fb37615 | ||
|
|
6403feaff9 | ||
|
|
47736910ca | ||
|
|
ead592a0bf | ||
|
|
d5bdba9244 | ||
|
|
4f033cec8d | ||
|
|
a58f4b2498 | ||
|
|
01522ed8c7 | ||
|
|
fa99ee9d5b | ||
|
|
6efe634850 | ||
|
|
60a1497eaf | ||
|
|
1d0cbc08df | ||
|
|
4d4280033b | ||
|
|
fd58775cae | ||
|
|
ccb0e93da2 | ||
|
|
c2a05da908 | ||
|
|
e1da9e60fc | ||
|
|
d044e535e0 | ||
|
|
293560dcd4 | ||
|
|
90ebb815d5 | ||
|
|
3d3d418ee6 | ||
|
|
f875cd05be | ||
|
|
435911489f | ||
|
|
5fcfcd53aa | ||
|
|
bc09215aad | ||
|
|
5f7e109e3d | ||
|
|
b75a5050d7 | ||
|
|
be497f7083 | ||
|
|
0ccae3e15b | ||
|
|
d736c32aec | ||
|
|
8ea5ba5d3f | ||
|
|
60c341befd | ||
|
|
be4f58ed8f | ||
|
|
d82d1abab6 | ||
|
|
0d81bd457c | ||
|
|
af2b19436f | ||
|
|
51beb3c7e4 | ||
|
|
5061456735 | ||
|
|
b01eb3af95 | ||
|
|
328bebc168 | ||
|
|
fc63fffa15 | ||
|
|
707584b2ef | ||
|
|
561459d93b | ||
|
|
25e48ae546 | ||
|
|
513bb3e8d0 | ||
|
|
04710ca908 | ||
|
|
fcf0fcf20c | ||
|
|
2ff40d8e37 | ||
|
|
1bab5b06a4 | ||
|
|
01cd4bcb47 | ||
|
|
49b2a559ae | ||
|
|
9212d24685 | ||
|
|
eb43b11202 | ||
|
|
5c4cae8c9d | ||
|
|
cfd7099743 | ||
|
|
19ae237d29 | ||
|
|
9cda78e561 | ||
|
|
cc31872a7f | ||
|
|
3c2c896708 | ||
|
|
b73da9c54c | ||
|
|
414a45bfb0 | ||
|
|
2a6f808bca | ||
|
|
cdf2a13bbd | ||
|
|
3e3e8a14ee | ||
|
|
37e180827a | ||
|
|
b047b54545 | ||
|
|
b7bb4bbd57 | ||
|
|
86cf2cd233 | ||
|
|
ab12c201b4 | ||
|
|
a8f03d859c | ||
|
|
3c7580f024 | ||
|
|
277833e388 | ||
|
|
eb16d7e6f9 | ||
|
|
1418068d2b | ||
|
|
774346f5f8 | ||
|
|
1aab88e6ca | ||
|
|
613f49b8bb | ||
|
|
5c95dc6e20 | ||
|
|
cbc2713bee | ||
|
|
2955975793 | ||
|
|
f8299d7f40 | ||
|
|
e855d44523 | ||
|
|
64e7715480 | ||
|
|
2e9a74f609 | ||
|
|
11a1230738 | ||
|
|
298373742e | ||
|
|
dc7aeecd85 | ||
|
|
15a7de7b24 | ||
|
|
714d0d4092 | ||
|
|
225d7f39d1 | ||
|
|
0005798c83 | ||
|
|
1d9078f9be | ||
|
|
510ac7005a | ||
|
|
c049b968a5 | ||
|
|
858698f7cd | ||
|
|
d104f6f8fc | ||
|
|
3ecf0d3230 | ||
|
|
6e4131fee4 | ||
|
|
41fa6bc8ed | ||
|
|
58a29bf058 | ||
|
|
7dac17de18 | ||
|
|
799d7de182 | ||
|
|
735af02f59 | ||
|
|
ad3f3799fa | ||
|
|
5f97df015e | ||
|
|
ff18fd2c38 | ||
|
|
3ab0cd02df | ||
|
|
c31072f42f | ||
|
|
c01c59023a | ||
|
|
4329aac377 | ||
|
|
c10b31e9d0 | ||
|
|
71a789c0b4 | ||
|
|
deb9847e2b | ||
|
|
9e9e7e1e96 | ||
|
|
d34e0341e2 | ||
|
|
aec254b05a | ||
|
|
f8b420047a | ||
|
|
7e6e4c0bc6 | ||
|
|
71fb59943c | ||
|
|
34419d0ca1 | ||
|
|
475a36f0d7 | ||
|
|
1234c1e7e2 | ||
|
|
a4a400facf | ||
|
|
ed2ca4d896 | ||
|
|
ce42e4d1cd | ||
|
|
b048128e77 | ||
|
|
635c257502 | ||
|
|
58a38c08d7 | ||
|
|
8fbee7737b | ||
|
|
e84f5f184e | ||
|
|
0bd26b19d7 | ||
|
|
64f82d5d51 | ||
|
|
f63ff994ce | ||
|
|
a10ee43271 | ||
|
|
54ed29e08d | ||
|
|
cc097e7a3f | ||
|
|
5de92ada43 | ||
|
|
0c546211cf | ||
|
|
4dc5a3a67c | ||
|
|
c51b226ceb | ||
|
|
0a5ca6cf74 | ||
|
|
96957219e4 | ||
|
|
32b7620db3 | ||
|
|
347f65e089 | ||
|
|
16628a427e | ||
|
|
ed16034a25 | ||
|
|
0c5f144e41 | ||
|
|
acc7d6e7dc | ||
|
|
84b4139052 | ||
|
|
9943643958 | ||
|
|
9ceaefb663 | ||
|
|
ec03ea5bc1 | ||
|
|
5855633c1f | ||
|
|
a53bc2bc2e | ||
|
|
88445820ed | ||
|
|
044ed3ae98 | ||
|
|
6f48012234 | ||
|
|
d344318dd4 | ||
|
|
6273dd3d83 | ||
|
|
0f3f3cbffd | ||
|
|
3244123b21 | ||
|
|
cba2ee3622 | ||
|
|
25ed925df5 | ||
|
|
8c5bd60bab | ||
|
|
c5510556a7 | ||
|
|
bbcfca84ef | ||
|
|
1260e94c2a | ||
|
|
8a02574303 | ||
|
|
c930f08348 | ||
|
|
5204acb5d0 | ||
|
|
784aaa98c9 | ||
|
|
745e2494bc | ||
|
|
c00792519d | ||
|
|
142fe5a12c | ||
|
|
5b127f232e | ||
|
|
c22bf01003 | ||
|
|
05e4911d6f | ||
|
|
9b551ef0ba | ||
|
|
56a8bb2349 | ||
|
|
8503c6a64d | ||
|
|
820f18da4d | ||
|
|
51a2432ebf | ||
|
|
6639534e97 | ||
|
|
0621577c7d | ||
|
|
26a507e3db | ||
|
|
244b540fe0 | ||
|
|
030ca4c173 | ||
|
|
88a2810f29 | ||
|
|
9164ee363a | ||
|
|
4cd47fdcc5 | ||
|
|
708852a3cb | ||
|
|
4a93bdf3ea | ||
|
|
22e7d2a811 | ||
|
|
93eca1dff2 | ||
|
|
9afe7408cd | ||
|
|
5dc2347a25 | ||
|
|
e3a0124b10 | ||
|
|
16af89c281 | ||
|
|
621e4258c8 | ||
|
|
ac6272e739 | ||
|
|
6e84f517a9 | ||
|
|
fdbdb3ad86 | ||
|
|
7adcf5ca46 | ||
|
|
fe6716cf76 | ||
|
|
3c2096db68 | ||
|
|
58cad1a6b3 | ||
|
|
662e67ff16 | ||
|
|
8d577b872f | ||
|
|
b55290f3cb | ||
|
|
e8d3eb7393 | ||
|
|
47fa16e35f | ||
|
|
a87f769b85 | ||
|
|
8e63fa4594 | ||
|
|
63501a0d59 | ||
|
|
828fb37ca8 | ||
|
|
40f513d3b6 | ||
|
|
f0b8b66a75 | ||
|
|
d51cdc068b | ||
|
|
f8b382e480 | ||
|
|
1995f43b67 | ||
|
|
69e0392a8b | ||
|
|
1f6319442e | ||
|
|
559c4c0c2c | ||
|
|
feeb5b58d9 | ||
|
|
7a00f79a56 | ||
|
|
10d744704a | ||
|
|
eee35f9cc3 | ||
|
|
b3656761eb | ||
|
|
7b5fe34316 | ||
|
|
4536780a19 | ||
|
|
05d866e6b3 | ||
|
|
0d138cf473 | ||
|
|
dbe539ac80 | ||
|
|
665a39d179 | ||
|
|
5fd5d8c8c5 | ||
|
|
2832b4564c | ||
|
|
d4369a64ee | ||
|
|
81fa1630b7 | ||
|
|
a1c4b35205 | ||
|
|
5e567f3e37 | ||
|
|
c4757684c1 | ||
|
|
a55a6bf94b | ||
|
|
fa1792eb77 | ||
|
|
93a8f6e759 | ||
|
|
4a614855d4 | ||
|
|
8bdd47f912 | ||
|
|
f9e82abadc | ||
|
|
428fda81e2 | ||
|
|
29c9ad602d | ||
|
|
44458e2a97 | ||
|
|
861fb1f54b | ||
|
|
02534f4d55 | ||
|
|
5532cb95a2 | ||
|
|
9176e43fc9 | ||
|
|
cb190f54fc | ||
|
|
4be2539bc2 | ||
|
|
291e2adffa | ||
|
|
fa2ec63f45 | ||
|
|
946c943457 | ||
|
|
0e50766d6e | ||
|
|
58a1610ae0 | ||
|
|
06dc21168a | ||
|
|
305b67fbed | ||
|
|
4da6d152c3 | ||
|
|
25630f1ef5 | ||
|
|
9b01e3f1c9 | ||
|
|
99450400eb | ||
|
|
2f8a8988d7 | ||
|
|
9104d2e89e | ||
|
|
e75022763c | ||
|
|
f0f3fb337d | ||
|
|
f7f01a34c2 | ||
|
|
f9f9ff0cb8 | ||
|
|
522ba05ba8 | ||
|
|
f4f4093466 | ||
|
|
2e16ab0c2c | ||
|
|
6f02606fb7 | ||
|
|
df40142b51 | ||
|
|
cc290d488b | ||
|
|
64328218fc | ||
|
|
8d1356a085 | ||
|
|
4f39dd0f73 | ||
|
|
54ffc8ae45 | ||
|
|
78ab1944bd | ||
|
|
434cf94657 | ||
|
|
dcb893e230 | ||
|
|
ce4fadc378 | ||
|
|
5683d1b1bd | ||
|
|
0eb88d0c10 | ||
|
|
eb1367e54d | ||
|
|
33a4786206 | ||
|
|
8c6606ad95 | ||
|
|
cde9519a76 | ||
|
|
7b2e0d79cb | ||
|
|
5b0da8e92a | ||
|
|
0126d2f77c | ||
|
|
0b436014c9 | ||
|
|
2cb7f223ed | ||
|
|
eca551ed98 | ||
|
|
608fd92861 | ||
|
|
e37d8fe45f | ||
|
|
4cce91ec97 | ||
|
|
72fdde35dc | ||
|
|
d425187778 | ||
|
|
e419aa1f1a | ||
|
|
5506547f7f | ||
|
|
568ed72b3e | ||
|
|
e8cc0e6684 | ||
|
|
4331f69395 | ||
|
|
7cc67ae7cb | ||
|
|
244b3438fc | ||
|
|
1a741f7ca0 | ||
|
|
1447800e2b | ||
|
|
f968fe7512 | ||
|
|
0a2349fad7 | ||
|
|
941b8cbc1e | ||
|
|
3b7b16acfd | ||
|
|
fbc7bb68fc | ||
|
|
0d16880596 | ||
|
|
3b5218128f | ||
|
|
cb731bf1db | ||
|
|
7c4d6eb02d | ||
|
|
c14e7fb17a | ||
|
|
fe57811bc5 | ||
|
|
e073b48f7d | ||
|
|
a9df609593 | ||
|
|
6c3db9646e | ||
|
|
ff9c4c717e | ||
|
|
182374b46f | ||
|
|
0871cda526 | ||
|
|
1b47cba37a | ||
|
|
e5bef36905 | ||
|
|
706d723703 | ||
|
|
51eacbfac5 | ||
|
|
5c2a411982 | ||
|
|
08d65cbc41 | ||
|
|
9d2bf429c1 | ||
|
|
d34f863bd4 | ||
|
|
b4abf1c2c7 | ||
|
|
68baaf589e | ||
|
|
be74e41d84 | ||
|
|
848122b0ec | ||
|
|
0edcb7c0d9 | ||
|
|
cc58e06b5e | ||
|
|
0d6ca606ea | ||
|
|
75ee93789f | ||
|
|
05daddafbf | ||
|
|
7bbce6725d | ||
|
|
789b211586 | ||
|
|
826a043748 | ||
|
|
6761048298 | ||
|
|
738fc9acad | ||
|
|
43c0540de7 | ||
|
|
2d1c3d8121 | ||
|
|
f48a5c650d | ||
|
|
66c18eddb8 | ||
|
|
fdd2ee6365 | ||
|
|
c207f60ad8 | ||
|
|
0eaa95c8c0 | ||
|
|
df2fca5935 | ||
|
|
dcaf5d9c7d | ||
|
|
0112969a97 | ||
|
|
3ec0f3d69c | ||
|
|
5555d300a1 | ||
|
|
8155ef4b60 | ||
|
|
a12402f6c8 | ||
|
|
cf28b814cb | ||
|
|
b05f67db19 | ||
|
|
260f4659d5 | ||
|
|
9e700f298c | ||
|
|
56510734c4 | ||
|
|
3938a4d14e | ||
|
|
fa3b9eeeaf | ||
|
|
eb9d6fa25c | ||
|
|
b53307c1c2 | ||
|
|
c3fc708a66 | ||
|
|
b34ffbe6d0 | ||
|
|
f364315e48 | ||
|
|
3ddb5a13a5 | ||
|
|
a24cc399a4 | ||
|
|
305f4b2688 | ||
|
|
9823171d65 | ||
|
|
4761bd8fda | ||
|
|
9c22698723 | ||
|
|
e3892bbcc6 | ||
|
|
629b156f52 | ||
|
|
c45dd47d34 | ||
|
|
ef8831f784 | ||
|
|
c5a42cf5de | ||
|
|
90ebbfc20f | ||
|
|
17cd0dc91d | ||
|
|
fa1f42af59 | ||
|
|
f45ea1ab53 | ||
|
|
0dde3fe483 | ||
|
|
277dc7dd09 | ||
|
|
3215d0b856 | ||
|
|
0167d5efcd | ||
|
|
b48ac808a6 | ||
|
|
616524775c | ||
|
|
5832849b11 | ||
|
|
467c5d01e9 | ||
|
|
24711a2f39 | ||
|
|
24e8286f35 | ||
|
|
e8a1378ad0 | ||
|
|
76bb418ea9 | ||
|
|
cd8770a3e3 | ||
|
|
da834c0935 | ||
|
|
024ffb1117 | ||
|
|
eed7ab9793 | ||
|
|
032feb343f | ||
|
|
eabccba3fa | ||
|
|
d86d656316 | ||
|
|
fa73c91b0b | ||
|
|
2eee50832d | ||
|
|
b40736918b | ||
|
|
ffb1a2e30f | ||
|
|
d6c3c0c6c1 | ||
|
|
ee251721ac | ||
|
|
fdbb9195d5 | ||
|
|
c68b08d9af | ||
|
|
3653bbfca0 | ||
|
|
05c7cc7277 | ||
|
|
5670bf099b | ||
|
|
0c324b0f09 | ||
|
|
968557e38e | ||
|
|
882cdebacb | ||
|
|
07753e1774 | ||
|
|
5b984507fc | ||
|
|
27df481967 | ||
|
|
0943031f23 | ||
|
|
2d95168de0 | ||
|
|
97cae8f92c | ||
|
|
eb213bac92 | ||
|
|
8187788b2c | ||
|
|
c80e08abce | ||
|
|
42fd851e5c | ||
|
|
70e4ebccab | ||
|
|
140f87c741 | ||
|
|
b0d756123e | ||
|
|
6188c92916 | ||
|
|
34c6f96728 | ||
|
|
50fd047c0b | ||
|
|
5bcc05b536 | ||
|
|
ce7d6c8dd5 | ||
|
|
d87a1e28b4 | ||
|
|
227306c572 | ||
|
|
45c2691f89 | ||
|
|
d0c81245b8 | ||
|
|
e494afb1aa | ||
|
|
ecc3c1cf3b | ||
|
|
228b16416a | ||
|
|
17eb74842a | ||
|
|
c01ff74c73 | ||
|
|
f88613b26d | ||
|
|
3464f4241f | ||
|
|
849b703828 | ||
|
|
4b935a40b6 | ||
|
|
5873a23ccb | ||
|
|
eae2786825 | ||
|
|
6407386de5 | ||
|
|
3fe950723f | ||
|
|
52bf6acd46 | ||
|
|
9590e7d7e0 | ||
|
|
7a08140a2d | ||
|
|
d1491cfbd1 | ||
|
|
695b80549d | ||
|
|
11c60a637f | ||
|
|
844ad70bb9 | ||
|
|
5ac7cde577 | ||
|
|
ce3ef0550f | ||
|
|
813f3e7d42 | ||
|
|
d03f97af6b | ||
|
|
019ab0286d | ||
|
|
c6647b4706 | ||
|
|
f913536d88 | ||
|
|
640d1bd176 | ||
|
|
66baccf528 | ||
|
|
6e6dacbace | ||
|
|
cdbb10fb26 | ||
|
|
c34ba3918c | ||
|
|
fa228c876c | ||
|
|
2f4d0af7d7 | ||
|
|
2d3e5235a9 | ||
|
|
8e91ccaa54 | ||
|
|
6955658b36 | ||
|
|
dbb44401fd | ||
|
|
b42ed70c84 | ||
|
|
a28276d823 | ||
|
|
fa4b27dd0e | ||
|
|
0be44d5c49 | ||
|
|
2514596276 | ||
|
|
7008d2a953 | ||
|
|
2539fedfc4 | ||
|
|
b453df7591 | ||
|
|
9e5d5edcba | ||
|
|
2d5de6ff99 | ||
|
|
259e9f1c17 | ||
|
|
daeb53009e | ||
|
|
f12d271ca5 | ||
|
|
965185ca3b | ||
|
|
9c484f6a78 | ||
|
|
de18c3c722 | ||
|
|
9be753b281 | ||
|
|
d6ae122de1 | ||
|
|
c6b90044f2 | ||
|
|
14898b6422 | ||
|
|
26294b0759 | ||
|
|
6da45b5c2b | ||
|
|
674332fddd | ||
|
|
ab8942d05a | ||
|
|
29790b8a5c | ||
|
|
4a4c26ffeb | ||
|
|
25c9bc07b2 | ||
|
|
d22d4c4c83 | ||
|
|
d88640fd20 | ||
|
|
57a2fca3a4 | ||
|
|
f796688c84 | ||
|
|
d6bbf8b7cc | ||
|
|
37ec460f64 | ||
|
|
004b9c95e4 | ||
|
|
86e27b465a | ||
|
|
5e9afddc3a | ||
|
|
de281535b1 | ||
|
|
9df7def14e | ||
|
|
5b9db9795d | ||
|
|
7d2ce7e6ab | ||
|
|
3e807af2b2 | ||
|
|
4c64dc7885 | ||
|
|
e7a7874b34 | ||
|
|
c78a47788b | ||
|
|
922698c5d9 | ||
|
|
8e8a490936 | ||
|
|
231bc0605f | ||
|
|
0298ff9478 | ||
|
|
33a25dcf0e | ||
|
|
54c16e3cdb | ||
|
|
28a978acc2 | ||
|
|
bea26a461f | ||
|
|
ed54c5b8b9 | ||
|
|
13316b68aa | ||
|
|
043986f35b | ||
|
|
2dc4421dd6 | ||
|
|
6c16e2bca2 | ||
|
|
c2b4a8e115 | ||
|
|
63b7bc8794 | ||
|
|
f41ae74ae2 | ||
|
|
98689d223e | ||
|
|
f19cf21146 | ||
|
|
24e19e6b18 | ||
|
|
08376cb15e | ||
|
|
5f6e4663c0 | ||
|
|
9b91c00fcc | ||
|
|
229ab88c2f | ||
|
|
8863d13578 | ||
|
|
e07fc9fbb9 | ||
|
|
0164574fdd | ||
|
|
98eec332d8 | ||
|
|
3d2986fc64 | ||
|
|
29e7f8581e | ||
|
|
4ee3f6c87a | ||
|
|
b8c7440e1f | ||
|
|
d49ff8d9a4 | ||
|
|
07198042bd | ||
|
|
c7a9492e96 | ||
|
|
360c6f3c1c | ||
|
|
89aab4acd5 | ||
|
|
d9b3e842d9 | ||
|
|
3ac4dc8392 | ||
|
|
0d1a5318ec | ||
|
|
94b7a219fd | ||
|
|
ba3eb71abd | ||
|
|
bbc9e11205 | ||
|
|
75571e4266 | ||
|
|
4e879271a0 | ||
|
|
552e0fefc3 | ||
|
|
cb7439a831 | ||
|
|
35d6b8bbc6 | ||
|
|
48b9220ffc | ||
|
|
5537981877 | ||
|
|
711f24a5b2 | ||
|
|
5d2b8bc8aa | ||
|
|
f6ea10db2d | ||
|
|
fc38ba3acb | ||
|
|
0830ad268f | ||
|
|
e633664c2a | ||
|
|
d4c7d9a60a | ||
|
|
5ee0d964f3 | ||
|
|
ba5e0f145f | ||
|
|
34eb9cc063 | ||
|
|
a795fdc40d | ||
|
|
24cba4c4ca | ||
|
|
3d13f4bb9b | ||
|
|
e713d0d321 | ||
|
|
4e34be87a1 | ||
|
|
07307d37a1 | ||
|
|
81463181bc | ||
|
|
02e57927fc | ||
|
|
36925f0dbd | ||
|
|
f9b985e03d | ||
|
|
598ad62b92 | ||
|
|
ea929ab713 | ||
|
|
04e56ced58 | ||
|
|
2278565b86 | ||
|
|
afd0c56b44 | ||
|
|
5ebdf66d22 | ||
|
|
177d8a72a7 | ||
|
|
03ef80dd8e | ||
|
|
6f9825362a | ||
|
|
2167154064 | ||
|
|
f88b35bd80 | ||
|
|
6b9520338e | ||
|
|
438c087856 | ||
|
|
2a43274b06 | ||
|
|
20a9336867 | ||
|
|
c921782714 | ||
|
|
776ac9e3d4 | ||
|
|
d02bd9b717 | ||
|
|
50070e8fe7 | ||
|
|
e3e3b3e279 | ||
|
|
38fba297e8 | ||
|
|
52d65ee4e8 | ||
|
|
9ad2f33dd8 | ||
|
|
02ae23b11d | ||
|
|
70c6d6e7ae | ||
|
|
8efebf992f | ||
|
|
b9be94bcc5 | ||
|
|
e6310c32ac | ||
|
|
654b4702d0 | ||
|
|
262b5a7ee5 | ||
|
|
ef0d4fe34b | ||
|
|
c08342f40c | ||
|
|
e7796268b5 | ||
|
|
0cbe80d2ab | ||
|
|
11d3ba70a0 | ||
|
|
c30e4c4867 | ||
|
|
d1e5087c18 | ||
|
|
618dd442e3 | ||
|
|
7f26fdf2d0 | ||
|
|
64090474e1 | ||
|
|
a69c28713a | ||
|
|
1d4b3095af | ||
|
|
ff75125af8 | ||
|
|
aa0025abbe | ||
|
|
c9436da235 | ||
|
|
12f1eaace7 | ||
|
|
09ef8aba0f | ||
|
|
08c094b8a5 | ||
|
|
e9fb4410cd | ||
|
|
cbdda22a33 | ||
|
|
fe906477da | ||
|
|
b03df619df | ||
|
|
53d89d8d17 | ||
|
|
1e5a1f3e1f | ||
|
|
6efe2979c6 | ||
|
|
92cc2c8e69 | ||
|
|
50dd2e4179 | ||
|
|
7a8fd9c3d3 | ||
|
|
d5a3fc490b | ||
|
|
13f948062b | ||
|
|
b965fda226 | ||
|
|
f9d67f0e9d | ||
|
|
4dfa20e40b | ||
|
|
d5edbaa3a9 | ||
|
|
0cd5ce8c29 | ||
|
|
1c50a87ca2 |
2
.github/CODEOWNERS
vendored
@@ -1 +1 @@
|
||||
* @prowler-cloud/prowler-team
|
||||
* @prowler-cloud/prowler-oss
|
||||
|
||||
52
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,52 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[Bug]: "
|
||||
labels: bug, status/needs-triage
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Please use this template to create your bug report. By providing as much info as possible you help us understand the issue, reproduce it and resolve it for you quicker. Therefore, take a couple of extra minutes to make sure you have provided all info needed.
|
||||
|
||||
PROTIP: record your screen and attach it as a gif to showcase the issue.
|
||||
|
||||
- How to record and attach gif: https://bit.ly/2Mi8T6K
|
||||
-->
|
||||
|
||||
**What happened?**
|
||||
A clear and concise description of what the bug is or what is not working as expected
|
||||
|
||||
|
||||
**How to reproduce it**
|
||||
Steps to reproduce the behavior:
|
||||
1. What command are you running?
|
||||
2. Cloud provider you are launching
|
||||
3. Environment you have like single account, multi-account, organizations, multi or single subsctiption, etc.
|
||||
4. See error
|
||||
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
|
||||
**Screenshots or Logs**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
Also, you can add logs (anonymize them first!). Here a command that may help to share a log
|
||||
`prowler <your arguments> --log-level DEBUG --log-file $(date +%F)_debug.log` then attach here the log file.
|
||||
|
||||
|
||||
**From where are you running Prowler?**
|
||||
Please, complete the following information:
|
||||
- Resource: (e.g. EC2 instance, Fargate task, Docker container manually, EKS, Cloud9, CodeBuild, workstation, etc.)
|
||||
- OS: [e.g. Amazon Linux 2, Mac, Alpine, Windows, etc. ]
|
||||
- Prowler Version [`./prowler --version`]:
|
||||
- Python version [`python --version`]:
|
||||
- Pip version [`pip --version`]:
|
||||
- Installation method (Are you running it from pip package or cloning the github repo?):
|
||||
- Others:
|
||||
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
97
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
name: 🐞 Bug Report
|
||||
description: Create a report to help us improve
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "status/needs-triage"]
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |-
|
||||
1. What command are you running?
|
||||
2. Cloud provider you are launching
|
||||
3. Environment you have, like single account, multi-account, organizations, multi or single subscription, etc.
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Result with Screenshots or Logs
|
||||
description: If applicable, add screenshots to help explain your problem. Also, you can add logs (anonymize them first!). Here a command that may help to share a log `prowler <your arguments> --log-level DEBUG --log-file $(date +%F)_debug.log` then attach here the log file.
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: type
|
||||
attributes:
|
||||
label: How did you install Prowler?
|
||||
options:
|
||||
- Cloning the repository from github.com (git clone)
|
||||
- From pip package (pip install prowler)
|
||||
- From brew (brew install prowler)
|
||||
- Docker (docker pull toniblyx/prowler)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment Resource
|
||||
description: From where are you running Prowler?
|
||||
placeholder: |-
|
||||
1. EC2 instance
|
||||
2. Fargate task
|
||||
3. Docker container locally
|
||||
4. EKS
|
||||
5. Cloud9
|
||||
6. CodeBuild
|
||||
7. Workstation
|
||||
8. Other(please specify)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: os
|
||||
attributes:
|
||||
label: OS used
|
||||
description: Which OS are you using?
|
||||
placeholder: |-
|
||||
1. Amazon Linux 2
|
||||
2. MacOS
|
||||
3. Alpine Linux
|
||||
4. Windows
|
||||
5. Other(please specify)
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: prowler-version
|
||||
attributes:
|
||||
label: Prowler version
|
||||
description: Which Prowler version are you using?
|
||||
placeholder: |-
|
||||
prowler --version
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: pip-version
|
||||
attributes:
|
||||
label: Pip version
|
||||
description: Which pip version are you using?
|
||||
placeholder: |-
|
||||
pip --version
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
description: Additional context
|
||||
label: Context
|
||||
validations:
|
||||
required: false
|
||||
36
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: 💡 Feature Request
|
||||
description: Suggest an idea for this project
|
||||
labels: ["enhancement", "status/needs-triage"]
|
||||
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: Problem
|
||||
attributes:
|
||||
label: New feature motivation
|
||||
description: Is your feature request related to a problem? Please describe
|
||||
placeholder: |-
|
||||
1. A clear and concise description of what the problem is. Ex. I'm always frustrated when
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: Solution
|
||||
attributes:
|
||||
label: Solution Proposed
|
||||
description: A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: Alternatives
|
||||
attributes:
|
||||
label: Describe alternatives you've considered
|
||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: Context
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context or screenshots about the feature request here.
|
||||
validations:
|
||||
required: false
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement, status/needs-triage
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
2
.github/dependabot.yml
vendored
@@ -8,7 +8,7 @@ updates:
|
||||
- package-ecosystem: "pip" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
target-branch: master
|
||||
labels:
|
||||
- "dependencies"
|
||||
|
||||
215
.github/workflows/build-lint-push-containers.yml
vendored
@@ -7,115 +7,56 @@ on:
|
||||
paths-ignore:
|
||||
- ".github/**"
|
||||
- "README.md"
|
||||
- "docs/**"
|
||||
|
||||
release:
|
||||
types: [published, edited]
|
||||
types: [published]
|
||||
|
||||
env:
|
||||
AWS_REGION_STG: eu-west-1
|
||||
AWS_REGION_PLATFORM: eu-west-1
|
||||
AWS_REGION_PRO: us-east-1
|
||||
AWS_REGION: us-east-1
|
||||
IMAGE_NAME: prowler
|
||||
LATEST_TAG: latest
|
||||
STABLE_TAG: stable
|
||||
TEMPORARY_TAG: temporary
|
||||
DOCKERFILE_PATH: ./Dockerfile
|
||||
PYTHON_VERSION: 3.9
|
||||
|
||||
jobs:
|
||||
# Lint Dockerfile using Hadolint
|
||||
# dockerfile-linter:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# -
|
||||
# name: Checkout
|
||||
# uses: actions/checkout@v3
|
||||
# -
|
||||
# name: Install Hadolint
|
||||
# run: |
|
||||
# VERSION=$(curl --silent "https://api.github.com/repos/hadolint/hadolint/releases/latest" | \
|
||||
# grep '"tag_name":' | \
|
||||
# sed -E 's/.*"v([^"]+)".*/\1/' \
|
||||
# ) && curl -L -o /tmp/hadolint https://github.com/hadolint/hadolint/releases/download/v${VERSION}/hadolint-Linux-x86_64 \
|
||||
# && chmod +x /tmp/hadolint
|
||||
# -
|
||||
# name: Run Hadolint
|
||||
# run: |
|
||||
# /tmp/hadolint util/Dockerfile
|
||||
|
||||
# Build Prowler OSS container
|
||||
container-build:
|
||||
container-build-push:
|
||||
# needs: dockerfile-linter
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
POETRY_VIRTUALENVS_CREATE: "false"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
# Without pushing to registries
|
||||
push: false
|
||||
tags: ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }}
|
||||
file: ${{ env.DOCKERFILE_PATH }}
|
||||
outputs: type=docker,dest=/tmp/${{ env.IMAGE_NAME }}.tar
|
||||
- name: Share image between jobs
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.IMAGE_NAME }}.tar
|
||||
path: /tmp/${{ env.IMAGE_NAME }}.tar
|
||||
|
||||
# Lint Prowler OSS container using Dockle
|
||||
# container-linter:
|
||||
# needs: container-build
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# -
|
||||
# name: Get container image from shared
|
||||
# uses: actions/download-artifact@v2
|
||||
# with:
|
||||
# name: ${{ env.IMAGE_NAME }}.tar
|
||||
# path: /tmp
|
||||
# -
|
||||
# name: Load Docker image
|
||||
# run: |
|
||||
# docker load --input /tmp/${{ env.IMAGE_NAME }}.tar
|
||||
# docker image ls -a
|
||||
# -
|
||||
# name: Install Dockle
|
||||
# run: |
|
||||
# VERSION=$(curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \
|
||||
# grep '"tag_name":' | \
|
||||
# sed -E 's/.*"v([^"]+)".*/\1/' \
|
||||
# ) && curl -L -o dockle.deb https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.deb \
|
||||
# && sudo dpkg -i dockle.deb && rm dockle.deb
|
||||
# -
|
||||
# name: Run Dockle
|
||||
# run: dockle ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }}
|
||||
|
||||
# Push Prowler OSS container to registries
|
||||
container-push:
|
||||
# needs: container-linter
|
||||
needs: container-build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read # This is required for actions/checkout
|
||||
steps:
|
||||
- name: Get container image from shared
|
||||
uses: actions/download-artifact@v2
|
||||
- name: Setup python (release)
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
name: ${{ env.IMAGE_NAME }}.tar
|
||||
path: /tmp
|
||||
- name: Load Docker image
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
|
||||
- name: Install dependencies (release)
|
||||
if: github.event_name == 'release'
|
||||
run: |
|
||||
docker load --input /tmp/${{ env.IMAGE_NAME }}.tar
|
||||
docker image ls -a
|
||||
pipx install poetry
|
||||
pipx inject poetry poetry-bumpversion
|
||||
|
||||
- name: Update Prowler version (release)
|
||||
if: github.event_name == 'release'
|
||||
run: |
|
||||
poetry version ${{ github.event.release.tag_name }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to Public ECR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
@@ -123,70 +64,54 @@ jobs:
|
||||
username: ${{ secrets.PUBLIC_ECR_AWS_ACCESS_KEY_ID }}
|
||||
password: ${{ secrets.PUBLIC_ECR_AWS_SECRET_ACCESS_KEY }}
|
||||
env:
|
||||
AWS_REGION: ${{ env.AWS_REGION_PRO }}
|
||||
- name: Configure AWS Credentials -- STG
|
||||
if: github.event_name == 'push'
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-region: ${{ env.AWS_REGION_STG }}
|
||||
role-to-assume: ${{ secrets.STG_IAM_ROLE_ARN }}
|
||||
role-session-name: build-lint-containers-stg
|
||||
- name: Login to ECR -- STG
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ secrets.STG_ECR }}
|
||||
- name: Configure AWS Credentials -- PLATFORM
|
||||
if: github.event_name == 'release'
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-region: ${{ env.AWS_REGION_PLATFORM }}
|
||||
role-to-assume: ${{ secrets.STG_IAM_ROLE_ARN }}
|
||||
role-session-name: build-lint-containers-pro
|
||||
- name: Login to ECR -- PLATFORM
|
||||
if: github.event_name == 'release'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ secrets.PLATFORM_ECR }}
|
||||
- # Push to master branch - push "latest" tag
|
||||
name: Tag (latest)
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }} ${{ secrets.PLATFORM_ECR }}/${{ secrets.PLATFORM_ECR_REPOSITORY }}:${{ env.LATEST_TAG }}
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }} ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.LATEST_TAG }}
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }} ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.LATEST_TAG }}
|
||||
- # Push to master branch - push "latest" tag
|
||||
name: Push (latest)
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
docker push ${{ secrets.PLATFORM_ECR }}/${{ secrets.PLATFORM_ECR_REPOSITORY }}:${{ env.LATEST_TAG }}
|
||||
docker push ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.LATEST_TAG }}
|
||||
docker push ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.LATEST_TAG }}
|
||||
- # Tag the new release (stable and release tag)
|
||||
name: Tag (release)
|
||||
if: github.event_name == 'release'
|
||||
run: |
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }} ${{ secrets.PLATFORM_ECR }}/${{ secrets.PLATFORM_ECR_REPOSITORY }}:${{ github.event.release.tag_name }}
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }} ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ github.event.release.tag_name }}
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }} ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ github.event.release.tag_name }}
|
||||
AWS_REGION: ${{ env.AWS_REGION }}
|
||||
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }} ${{ secrets.PLATFORM_ECR }}/${{ secrets.PLATFORM_ECR_REPOSITORY }}:${{ env.STABLE_TAG }}
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }} ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.STABLE_TAG }}
|
||||
docker tag ${{ env.IMAGE_NAME }}:${{ env.TEMPORARY_TAG }} ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.STABLE_TAG }}
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- # Push the new release (stable and release tag)
|
||||
name: Push (release)
|
||||
- name: Build and push container image (latest)
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: |
|
||||
${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.LATEST_TAG }}
|
||||
${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.LATEST_TAG }}
|
||||
file: ${{ env.DOCKERFILE_PATH }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Build and push container image (release)
|
||||
if: github.event_name == 'release'
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
# Use local context to get changes
|
||||
# https://github.com/docker/build-push-action#path-context
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ github.event.release.tag_name }}
|
||||
${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.STABLE_TAG }}
|
||||
${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ github.event.release.tag_name }}
|
||||
${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.STABLE_TAG }}
|
||||
file: ${{ env.DOCKERFILE_PATH }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
dispatch-action:
|
||||
needs: container-build-push
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get latest commit info
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
LATEST_COMMIT_HASH=$(echo ${{ github.event.after }} | cut -b -7)
|
||||
echo "LATEST_COMMIT_HASH=${LATEST_COMMIT_HASH}" >> $GITHUB_ENV
|
||||
- name: Dispatch event for latest
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
curl https://api.github.com/repos/${{ secrets.DISPATCH_OWNER }}/${{ secrets.DISPATCH_REPO }}/dispatches -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.ACCESS_TOKEN }}" -H "X-GitHub-Api-Version: 2022-11-28" --data '{"event_type":"dispatch","client_payload":{"version":"latest", "tag": "${{ env.LATEST_COMMIT_HASH }}"}}'
|
||||
- name: Dispatch event for release
|
||||
if: github.event_name == 'release'
|
||||
run: |
|
||||
docker push ${{ secrets.PLATFORM_ECR }}/${{ secrets.PLATFORM_ECR_REPOSITORY }}:${{ github.event.release.tag_name }}
|
||||
docker push ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ github.event.release.tag_name }}
|
||||
docker push ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ github.event.release.tag_name }}
|
||||
|
||||
docker push ${{ secrets.PLATFORM_ECR }}/${{ secrets.PLATFORM_ECR_REPOSITORY }}:${{ env.STABLE_TAG }}
|
||||
docker push ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.STABLE_TAG }}
|
||||
docker push ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ env.STABLE_TAG }}
|
||||
- name: Delete artifacts
|
||||
if: always()
|
||||
uses: geekyeggo/delete-artifact@v1
|
||||
with:
|
||||
name: ${{ env.IMAGE_NAME }}.tar
|
||||
curl https://api.github.com/repos/${{ secrets.DISPATCH_OWNER }}/${{ secrets.DISPATCH_REPO }}/dispatches -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.ACCESS_TOKEN }}" -H "X-GitHub-Api-Version: 2022-11-28" --data '{"event_type":"dispatch","client_payload":{"version":"release", "tag":"${{ github.event.release.tag_name }}"}}'
|
||||
|
||||
57
.github/workflows/codeql.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master", prowler-2, prowler-3.0-dev ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '00 12 * * *'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'python' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
34
.github/workflows/pull-request.yml
vendored
@@ -13,46 +13,56 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9"]
|
||||
python-version: ["3.9", "3.10", "3.11"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install poetry
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pipx install poetry
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: "poetry"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install pipenv
|
||||
pipenv install --dev
|
||||
pipenv run pip list
|
||||
poetry install
|
||||
poetry run pip list
|
||||
VERSION=$(curl --silent "https://api.github.com/repos/hadolint/hadolint/releases/latest" | \
|
||||
grep '"tag_name":' | \
|
||||
sed -E 's/.*"v([^"]+)".*/\1/' \
|
||||
) && curl -L -o /tmp/hadolint "https://github.com/hadolint/hadolint/releases/download/v${VERSION}/hadolint-Linux-x86_64" \
|
||||
&& chmod +x /tmp/hadolint
|
||||
- name: Poetry check
|
||||
run: |
|
||||
poetry lock --check
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
pipenv run flake8 . --ignore=E266,W503,E203,E501,W605,E128 --exclude contrib
|
||||
poetry run flake8 . --ignore=E266,W503,E203,E501,W605,E128 --exclude contrib
|
||||
- name: Checking format with black
|
||||
run: |
|
||||
pipenv run black --check .
|
||||
poetry run black --check .
|
||||
- name: Lint with pylint
|
||||
run: |
|
||||
pipenv run pylint --disable=W,C,R,E -j 0 -rn -sn prowler/
|
||||
poetry run pylint --disable=W,C,R,E -j 0 -rn -sn prowler/
|
||||
- name: Bandit
|
||||
run: |
|
||||
pipenv run bandit -q -lll -x '*_test.py,./contrib/' -r .
|
||||
poetry run bandit -q -lll -x '*_test.py,./contrib/' -r .
|
||||
- name: Safety
|
||||
run: |
|
||||
pipenv run safety check
|
||||
poetry run safety check
|
||||
- name: Vulture
|
||||
run: |
|
||||
pipenv run vulture --exclude "contrib" --min-confidence 100 .
|
||||
poetry run vulture --exclude "contrib" --min-confidence 100 .
|
||||
- name: Hadolint
|
||||
run: |
|
||||
/tmp/hadolint Dockerfile --ignore=DL3013
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
pipenv run pytest tests -n auto
|
||||
poetry run pytest -n auto --cov=./prowler --cov-report=xml tests
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
79
.github/workflows/pypi-release.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
name: pypi-release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
||||
GITHUB_BRANCH: master
|
||||
|
||||
jobs:
|
||||
release-prowler-job:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
POETRY_VIRTUALENVS_CREATE: "false"
|
||||
name: Release Prowler to PyPI
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ env.GITHUB_BRANCH }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pipx install poetry
|
||||
pipx inject poetry poetry-bumpversion
|
||||
- name: setup python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.9
|
||||
cache: 'poetry'
|
||||
- name: Change version and Build package
|
||||
run: |
|
||||
poetry version ${{ env.RELEASE_TAG }}
|
||||
git config user.name "github-actions"
|
||||
git config user.email "<noreply@github.com>"
|
||||
git add prowler/config/config.py pyproject.toml
|
||||
git commit -m "chore(release): ${{ env.RELEASE_TAG }}" --no-verify
|
||||
git tag -fa ${{ env.RELEASE_TAG }} -m "chore(release): ${{ env.RELEASE_TAG }}"
|
||||
git push -f origin ${{ env.RELEASE_TAG }}
|
||||
poetry build
|
||||
- name: Publish prowler package to PyPI
|
||||
run: |
|
||||
poetry config pypi-token.pypi ${{ secrets.PYPI_API_TOKEN }}
|
||||
poetry publish
|
||||
# Create pull request with new version
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
token: ${{ secrets.PROWLER_ACCESS_TOKEN }}
|
||||
commit-message: "chore(release): update Prowler Version to ${{ env.RELEASE_TAG }}."
|
||||
branch: release-${{ env.RELEASE_TAG }}
|
||||
labels: "status/waiting-for-revision, severity/low"
|
||||
title: "chore(release): update Prowler Version to ${{ env.RELEASE_TAG }}"
|
||||
body: |
|
||||
### Description
|
||||
|
||||
This PR updates Prowler Version to ${{ env.RELEASE_TAG }}.
|
||||
|
||||
### License
|
||||
|
||||
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
|
||||
- name: Replicate PyPi Package
|
||||
run: |
|
||||
rm -rf ./dist && rm -rf ./build && rm -rf prowler.egg-info
|
||||
pip install toml
|
||||
python util/replicate_pypi_package.py
|
||||
poetry build
|
||||
- name: Publish prowler-cloud package to PyPI
|
||||
run: |
|
||||
poetry config pypi-token.pypi ${{ secrets.PYPI_API_TOKEN }}
|
||||
poetry publish
|
||||
# Create pull request to github.com/Homebrew/homebrew-core to update prowler formula
|
||||
- name: Bump Homebrew formula
|
||||
uses: mislav/bump-homebrew-formula-action@v2
|
||||
with:
|
||||
formula-name: prowler
|
||||
base-branch: release-${{ env.RELEASE_TAG }}
|
||||
env:
|
||||
COMMITTER_TOKEN: ${{ secrets.PROWLER_ACCESS_TOKEN }}
|
||||
@@ -19,6 +19,7 @@ jobs:
|
||||
permissions:
|
||||
id-token: write
|
||||
pull-requests: write
|
||||
contents: write
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
@@ -51,11 +52,11 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
token: ${{ secrets.PROWLER_ACCESS_TOKEN }}
|
||||
commit-message: "feat(regions_update): Update regions for AWS services."
|
||||
branch: "aws-services-regions-updated"
|
||||
branch: "aws-services-regions-updated-${{ github.sha }}"
|
||||
labels: "status/waiting-for-revision, severity/low"
|
||||
title: "feat(regions_update): Changes in regions for AWS services."
|
||||
title: "chore(regions_update): Changes in regions for AWS services."
|
||||
body: |
|
||||
### Description
|
||||
|
||||
|
||||
5
.gitignore
vendored
@@ -46,3 +46,8 @@ junit-reports/
|
||||
|
||||
# .env
|
||||
.env*
|
||||
|
||||
# Coverage
|
||||
.coverage*
|
||||
.coverage
|
||||
coverage*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
repos:
|
||||
## GENERAL
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: check-merge-conflict
|
||||
- id: check-yaml
|
||||
@@ -13,14 +13,22 @@ repos:
|
||||
- id: pretty-format-json
|
||||
args: ["--autofix", --no-sort-keys, --no-ensure-ascii]
|
||||
|
||||
## TOML
|
||||
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
|
||||
rev: v2.10.0
|
||||
hooks:
|
||||
- id: pretty-format-toml
|
||||
args: [--autofix]
|
||||
files: pyproject.toml
|
||||
|
||||
## BASH
|
||||
- repo: https://github.com/koalaman/shellcheck-precommit
|
||||
rev: v0.8.0
|
||||
rev: v0.9.0
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
## PYTHON
|
||||
- repo: https://github.com/myint/autoflake
|
||||
rev: v1.7.7
|
||||
rev: v2.2.0
|
||||
hooks:
|
||||
- id: autoflake
|
||||
args:
|
||||
@@ -31,30 +39,32 @@ repos:
|
||||
]
|
||||
|
||||
- repo: https://github.com/timothycrosley/isort
|
||||
rev: 5.10.1
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
- id: isort
|
||||
args: ["--profile", "black"]
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.10.0
|
||||
rev: 22.12.0
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 5.0.4
|
||||
rev: 6.1.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
exclude: contrib
|
||||
args: ["--ignore=E266,W503,E203,E501,W605"]
|
||||
|
||||
- repo: https://github.com/haizaar/check-pipfile-lock
|
||||
rev: v0.0.5
|
||||
- repo: https://github.com/python-poetry/poetry
|
||||
rev: 1.6.0 # add version here
|
||||
hooks:
|
||||
- id: check-pipfile-lock
|
||||
- id: poetry-check
|
||||
- id: poetry-lock
|
||||
args: ["--no-update"]
|
||||
|
||||
- repo: https://github.com/hadolint/hadolint
|
||||
rev: v2.12.0
|
||||
rev: v2.12.1-beta
|
||||
hooks:
|
||||
- id: hadolint
|
||||
args: ["--ignore=DL3013"]
|
||||
@@ -66,6 +76,15 @@ repos:
|
||||
entry: bash -c 'pylint --disable=W,C,R,E -j 0 -rn -sn prowler/'
|
||||
language: system
|
||||
|
||||
- id: trufflehog
|
||||
name: TruffleHog
|
||||
description: Detect secrets in your data.
|
||||
# entry: bash -c 'trufflehog git file://. --only-verified --fail'
|
||||
# For running trufflehog in docker, use the following entry instead:
|
||||
entry: bash -c 'docker run -v "$(pwd):/workdir" -i --rm trufflesecurity/trufflehog:latest git file:///workdir --only-verified --fail'
|
||||
language: system
|
||||
stages: ["commit", "push"]
|
||||
|
||||
- id: pytest-check
|
||||
name: pytest-check
|
||||
entry: bash -c 'pytest tests -n auto'
|
||||
|
||||
23
.readthedocs.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
build:
|
||||
os: "ubuntu-22.04"
|
||||
tools:
|
||||
python: "3.9"
|
||||
jobs:
|
||||
post_create_environment:
|
||||
# Install poetry
|
||||
# https://python-poetry.org/docs/#installing-manually
|
||||
- pip install poetry
|
||||
# Tell poetry to not use a virtual environment
|
||||
- poetry config virtualenvs.create false
|
||||
post_install:
|
||||
- poetry install -E docs
|
||||
|
||||
mkdocs:
|
||||
configuration: mkdocs.yml
|
||||
13
CONTRIBUTING.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Do you want to learn on how to...
|
||||
|
||||
- Contribute with your code or fixes to Prowler
|
||||
- Create a new check for a provider
|
||||
- Create a new security compliance framework
|
||||
- Add a custom output format
|
||||
- Add a new integration
|
||||
- Contribute with documentation
|
||||
|
||||
Want some swag as appreciation for your contribution?
|
||||
|
||||
# Prowler Developer Guide
|
||||
https://docs.prowler.cloud/en/latest/tutorials/developer-guide/
|
||||
@@ -16,6 +16,7 @@ USER prowler
|
||||
WORKDIR /home/prowler
|
||||
COPY prowler/ /home/prowler/prowler/
|
||||
COPY pyproject.toml /home/prowler
|
||||
COPY README.md /home/prowler
|
||||
|
||||
# Install dependencies
|
||||
ENV HOME='/home/prowler'
|
||||
@@ -24,4 +25,9 @@ ENV PATH="$HOME/.local/bin:$PATH"
|
||||
RUN pip install --no-cache-dir --upgrade pip && \
|
||||
pip install --no-cache-dir .
|
||||
|
||||
# Remove Prowler directory and build files
|
||||
USER 0
|
||||
RUN rm -rf /home/prowler/prowler /home/prowler/pyproject.toml /home/prowler/README.md /home/prowler/build /home/prowler/prowler.egg-info
|
||||
|
||||
USER prowler
|
||||
ENTRYPOINT ["prowler"]
|
||||
|
||||
15
Makefile
@@ -2,12 +2,19 @@
|
||||
|
||||
##@ Testing
|
||||
test: ## Test with pytest
|
||||
pytest -n auto -vvv -s -x
|
||||
rm -rf .coverage && \
|
||||
pytest -n auto -vvv -s --cov=./prowler --cov-report=xml tests
|
||||
|
||||
coverage: ## Show Test Coverage
|
||||
coverage run --skip-covered -m pytest -v && \
|
||||
coverage report -m && \
|
||||
rm -rf .coverage
|
||||
rm -rf .coverage && \
|
||||
coverage report -m
|
||||
|
||||
coverage-html: ## Show Test Coverage
|
||||
rm -rf ./htmlcov && \
|
||||
coverage html && \
|
||||
open htmlcov/index.html
|
||||
|
||||
##@ Linting
|
||||
format: ## Format Code
|
||||
@@ -24,11 +31,11 @@ lint: ## Lint Code
|
||||
|
||||
##@ PyPI
|
||||
pypi-clean: ## Delete the distribution files
|
||||
rm -rf ./dist && rm -rf ./build && rm -rf prowler_cloud.egg-info
|
||||
rm -rf ./dist && rm -rf ./build && rm -rf prowler.egg-info
|
||||
|
||||
pypi-build: ## Build package
|
||||
$(MAKE) pypi-clean && \
|
||||
python3 -m build
|
||||
poetry build
|
||||
|
||||
pypi-upload: ## Upload package
|
||||
python3 -m twine upload --repository pypi dist/*
|
||||
|
||||
41
Pipfile
@@ -1,41 +0,0 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
colorama = "0.4.4"
|
||||
boto3 = "1.26.3"
|
||||
arnparse = "0.0.2"
|
||||
botocore = "1.27.8"
|
||||
pydantic = "1.9.1"
|
||||
shodan = "1.28.0"
|
||||
detect-secrets = "1.4.0"
|
||||
alive-progress = "2.4.1"
|
||||
tabulate = "0.9.0"
|
||||
azure-identity = "1.12.0"
|
||||
azure-storage-blob = "12.14.1"
|
||||
msgraph-core = "0.2.2"
|
||||
azure-mgmt-subscription = "3.1.1"
|
||||
azure-mgmt-authorization = "3.0.0"
|
||||
azure-mgmt-security = "3.0.0"
|
||||
azure-mgmt-storage = "21.0.0"
|
||||
|
||||
[dev-packages]
|
||||
black = "22.10.0"
|
||||
pylint = "2.15.9"
|
||||
flake8 = "5.0.4"
|
||||
bandit = "1.7.4"
|
||||
safety = "2.3.1"
|
||||
vulture = "2.6"
|
||||
moto = "4.0.13"
|
||||
docker = "6.0.0"
|
||||
openapi-spec-validator = "0.5.1"
|
||||
pytest = "7.1.2"
|
||||
pytest-xdist = "2.5.0"
|
||||
coverage = "7.0.3"
|
||||
sure = "2.0.0"
|
||||
freezegun = "1.2.1"
|
||||
|
||||
[requires]
|
||||
python_version = "3.9"
|
||||
1511
Pipfile.lock
generated
82
README.md
@@ -11,12 +11,14 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://join.slack.com/t/prowler-workspace/shared_invite/zt-1hix76xsl-2uq222JIXrC7Q8It~9ZNog"><img alt="Slack Shield" src="https://img.shields.io/badge/slack-prowler-brightgreen.svg?logo=slack"></a>
|
||||
<a href="https://pypi.org/project/prowler-cloud/"><img alt="Python Version" src="https://img.shields.io/pypi/v/prowler-cloud.svg"></a>
|
||||
<a href="https://pypi.python.org/pypi/prowler-cloud/"><img alt="Python Version" src="https://img.shields.io/pypi/pyversions/prowler-cloud.svg"></a>
|
||||
<a href="https://pypi.org/project/prowler/"><img alt="Python Version" src="https://img.shields.io/pypi/v/prowler.svg"></a>
|
||||
<a href="https://pypi.python.org/pypi/prowler/"><img alt="Python Version" src="https://img.shields.io/pypi/pyversions/prowler.svg"></a>
|
||||
<a href="https://pypistats.org/packages/prowler"><img alt="PyPI Prowler Downloads" src="https://img.shields.io/pypi/dw/prowler.svg?label=prowler%20downloads"></a>
|
||||
<a href="https://pypistats.org/packages/prowler-cloud"><img alt="PyPI Prowler-Cloud Downloads" src="https://img.shields.io/pypi/dw/prowler-cloud.svg?label=prowler-cloud%20downloads"></a>
|
||||
<a href="https://hub.docker.com/r/toniblyx/prowler"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/toniblyx/prowler"></a>
|
||||
<a href="https://hub.docker.com/r/toniblyx/prowler"><img alt="Docker" src="https://img.shields.io/docker/cloud/build/toniblyx/prowler"></a>
|
||||
<a href="https://hub.docker.com/r/toniblyx/prowler"><img alt="Docker" src="https://img.shields.io/docker/image-size/toniblyx/prowler"></a>
|
||||
<a href="https://gallery.ecr.aws/o4g1s5r6/prowler"><img width="120" height=19" alt="AWS ECR Gallery" src="https://user-images.githubusercontent.com/3985464/151531396-b6535a68-c907-44eb-95a1-a09508178616.png"></a>
|
||||
<a href="https://gallery.ecr.aws/prowler-cloud/prowler"><img width="120" height=19" alt="AWS ECR Gallery" src="https://user-images.githubusercontent.com/3985464/151531396-b6535a68-c907-44eb-95a1-a09508178616.png"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/prowler-cloud/prowler"><img alt="Repo size" src="https://img.shields.io/github/repo-size/prowler-cloud/prowler"></a>
|
||||
@@ -31,21 +33,34 @@
|
||||
|
||||
# Description
|
||||
|
||||
`Prowler` is an Open Source security tool to perform AWS and Azure security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness.
|
||||
`Prowler` is an Open Source security tool to perform AWS, GCP and Azure security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness.
|
||||
|
||||
It contains hundreds of controls covering CIS, PCI-DSS, ISO27001, GDPR, HIPAA, FFIEC, SOC2, AWS FTR, ENS and custom security frameworks.
|
||||
It contains hundreds of controls covering CIS, NIST 800, NIST CSF, CISA, RBI, FedRAMP, PCI-DSS, GDPR, HIPAA, FFIEC, SOC2, GXP, AWS Well-Architected Framework Security Pillar, AWS Foundational Technical Review (FTR), ENS (Spanish National Security Scheme) and your custom security frameworks.
|
||||
|
||||
| Provider | Checks | Services | [Compliance Frameworks](https://docs.prowler.cloud/en/latest/tutorials/compliance/) | [Categories](https://docs.prowler.cloud/en/latest/tutorials/misc/#categories) |
|
||||
|---|---|---|---|---|
|
||||
| AWS | 290 | 56 -> `prowler aws --list-services` | 25 -> `prowler aws --list-compliance` | 5 -> `prowler aws --list-categories` |
|
||||
| GCP | 73 | 11 -> `prowler gcp --list-services` | 1 -> `prowler gcp --list-compliance` | 2 -> `prowler gcp --list-categories`|
|
||||
| Azure | 23 | 4 -> `prowler azure --list-services` | CIS soon | 1 -> `prowler azure --list-categories` |
|
||||
| Kubernetes | Planned | - | - | - |
|
||||
|
||||
# 📖 Documentation
|
||||
|
||||
The full documentation can now be found at [https://docs.prowler.cloud](https://docs.prowler.cloud)
|
||||
|
||||
## Looking for Prowler v2 documentation?
|
||||
For Prowler v2 Documentation, please go to https://github.com/prowler-cloud/prowler/tree/2.12.1.
|
||||
|
||||
# ⚙️ Install
|
||||
|
||||
## Pip package
|
||||
Prowler is available as a project in [PyPI](https://pypi.org/project/prowler-cloud/), thus can be installed using pip with Python >= 3.9:
|
||||
|
||||
```console
|
||||
pip install prowler-cloud
|
||||
pip install prowler
|
||||
prowler -v
|
||||
```
|
||||
More details at https://docs.prowler.cloud
|
||||
|
||||
## Containers
|
||||
|
||||
@@ -58,34 +73,29 @@ The available versions of Prowler are the following:
|
||||
The container images are available here:
|
||||
|
||||
- [DockerHub](https://hub.docker.com/r/toniblyx/prowler/tags)
|
||||
- [AWS Public ECR](https://gallery.ecr.aws/o4g1s5r6/prowler)
|
||||
- [AWS Public ECR](https://gallery.ecr.aws/prowler-cloud/prowler)
|
||||
|
||||
## From Github
|
||||
|
||||
Python >= 3.9 is required with pip and pipenv:
|
||||
Python >= 3.9 is required with pip and poetry:
|
||||
|
||||
```
|
||||
git clone https://github.com/prowler-cloud/prowler
|
||||
cd prowler
|
||||
pipenv shell
|
||||
pipenv install
|
||||
poetry shell
|
||||
poetry install
|
||||
python prowler.py -v
|
||||
```
|
||||
|
||||
# 📖 Documentation
|
||||
|
||||
The full documentation now can be found at [https://docs.prowler.cloud](https://docs.prowler.cloud)
|
||||
|
||||
|
||||
# 📐✏️ High level architecture
|
||||
|
||||
You can run Prowler from your workstation, an EC2 instance, Fargate or any other container, Codebuild, CloudShell and Cloud9.
|
||||
|
||||

|
||||

|
||||
|
||||
# 📝 Requirements
|
||||
|
||||
Prowler has been written in Python using the [AWS SDK (Boto3)](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html#) and [Azure SDK](https://azure.github.io/azure-sdk-for-python/).
|
||||
Prowler has been written in Python using the [AWS SDK (Boto3)](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html#), [Azure SDK](https://azure.github.io/azure-sdk-for-python/) and [GCP API Python Client](https://github.com/googleapis/google-api-python-client/).
|
||||
## AWS
|
||||
|
||||
Since Prowler uses AWS Credentials under the hood, you can follow any authentication method as described [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-precedence).
|
||||
@@ -105,8 +115,8 @@ Make sure you have properly configured your AWS-CLI with a valid Access Key and
|
||||
|
||||
Those credentials must be associated to a user or role with proper permissions to do all checks. To make sure, add the following AWS managed policies to the user or role being used:
|
||||
|
||||
- arn:aws:iam::aws:policy/SecurityAudit
|
||||
- arn:aws:iam::aws:policy/job-function/ViewOnlyAccess
|
||||
- `arn:aws:iam::aws:policy/SecurityAudit`
|
||||
- `arn:aws:iam::aws:policy/job-function/ViewOnlyAccess`
|
||||
|
||||
> Moreover, some read-only additional permissions are needed for several checks, make sure you attach also the custom policy [prowler-additions-policy.json](https://github.com/prowler-cloud/prowler/blob/master/permissions/prowler-additions-policy.json) to the role you are using.
|
||||
|
||||
@@ -123,7 +133,7 @@ Those credentials must be associated to a user or role with proper permissions t
|
||||
|
||||
### Service Principal authentication
|
||||
|
||||
To allow Prowler assume the service principal identity to start the scan it is needed to configure the following environment variables:
|
||||
To allow Prowler assume the service principal identity to start the scan, it is needed to configure the following environment variables:
|
||||
|
||||
```console
|
||||
export AZURE_CLIENT_ID="XXXXXXXXX"
|
||||
@@ -134,11 +144,11 @@ export AZURE_CLIENT_SECRET="XXXXXXX"
|
||||
If you try to execute Prowler with the `--sp-env-auth` flag and those variables are empty or not exported, the execution is going to fail.
|
||||
### AZ CLI / Browser / Managed Identity authentication
|
||||
|
||||
The other three cases does not need additional configuration, `--az-cli-auth` and `--managed-identity-auth` are automated options, `--browser-auth` needs the user to authenticate using the default browser to start the scan.
|
||||
The other three cases do not need additional configuration, `--az-cli-auth` and `--managed-identity-auth` are automated options, `--browser-auth` needs the user to authenticate using the default browser to start the scan. Also `--browser-auth` needs the tenant id to be specified with `--tenant-id`.
|
||||
|
||||
### Permissions
|
||||
|
||||
To use each one you need to pass the proper flag to the execution. Prowler for Azure handles two types of permission scopes, which are:
|
||||
To use each one, you need to pass the proper flag to the execution. Prowler for Azure handles two types of permission scopes, which are:
|
||||
|
||||
- **Azure Active Directory permissions**: Used to retrieve metadata from the identity assumed by Prowler and future AAD checks (not mandatory to have access to execute the tool)
|
||||
- **Subscription scope permissions**: Required to launch the checks against your resources, mandatory to launch the tool.
|
||||
@@ -160,6 +170,22 @@ Regarding the subscription scope, Prowler by default scans all the subscriptions
|
||||
- `Reader`
|
||||
|
||||
|
||||
## Google Cloud Platform
|
||||
|
||||
Prowler will follow the same credentials search as [Google authentication libraries](https://cloud.google.com/docs/authentication/application-default-credentials#search_order):
|
||||
|
||||
1. [GOOGLE_APPLICATION_CREDENTIALS environment variable](https://cloud.google.com/docs/authentication/application-default-credentials#GAC)
|
||||
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
||||
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
||||
|
||||
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the following roles to the member associated with the credentials:
|
||||
|
||||
- Viewer
|
||||
- Security Reviewer
|
||||
- Stackdriver Account Viewer
|
||||
|
||||
> By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
|
||||
|
||||
# 💻 Basic Usage
|
||||
|
||||
To run prowler, you will need to specify the provider (e.g aws or azure):
|
||||
@@ -234,12 +260,14 @@ prowler azure [--sp-env-auth, --az-cli-auth, --browser-auth, --managed-identity-
|
||||
```
|
||||
> By default, `prowler` will scan all Azure subscriptions.
|
||||
|
||||
# 🎉 New Features
|
||||
## Google Cloud Platform
|
||||
|
||||
- Python: we got rid of all bash and it is now all in Python.
|
||||
- Faster: huge performance improvements (same account from 2.5 hours to 4 minutes).
|
||||
- Developers and community: we have made it easier to contribute with new checks and new compliance frameworks. We also included unit tests.
|
||||
- Multi-cloud: in addition to AWS, we have added Azure, we plan to include GCP and OCI soon, let us know if you want to contribute!
|
||||
Optionally, you can provide the location of an application credential JSON file with the following argument:
|
||||
|
||||
```console
|
||||
prowler gcp --credentials-file path
|
||||
```
|
||||
> By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
|
||||
|
||||
# 📃 License
|
||||
|
||||
|
||||
23
SECURITY.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Security Policy
|
||||
|
||||
## Software Security
|
||||
As an **AWS Partner** and we have passed the [AWS Foundation Technical Review (FTR)](https://aws.amazon.com/partners/foundational-technical-review/) and we use the following tools and automation to make sure our code is secure and dependencies up-to-dated:
|
||||
|
||||
- `bandit` for code security review.
|
||||
- `safety` and `dependabot` for dependencies.
|
||||
- `hadolint` and `dockle` for our containers security.
|
||||
- `snyk` in Docker Hub.
|
||||
- `clair` in Amazon ECR.
|
||||
- `vulture`, `flake8`, `black` and `pylint` for formatting and best practices.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you would like to report a vulnerability or have a security concern regarding Prowler Open Source or ProwlerPro service, please submit the information by contacting to help@prowler.pro.
|
||||
|
||||
The information you share with Verica as part of this process is kept confidential within Verica and the Prowler team. We will only share this information with a third party if the vulnerability you report is found to affect a third-party product, in which case we will share this information with the third-party product's author or manufacturer. Otherwise, we will only share this information as permitted by you.
|
||||
|
||||
We will review the submitted report, and assign it a tracking number. We will then respond to you, acknowledging receipt of the report, and outline the next steps in the process.
|
||||
|
||||
You will receive a non-automated response to your initial contact within 24 hours, confirming receipt of your reported vulnerability.
|
||||
|
||||
We will coordinate public notification of any validated vulnerability with you. Where possible, we prefer that our respective public disclosures be posted simultaneously.
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"Provider": "aws",
|
||||
"CheckID": "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"CheckTitle": "Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to SSH port 22.",
|
||||
"CheckType": "Data Protection",
|
||||
"ServiceName": "ec2",
|
||||
"SubServiceName": "securitygroup",
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
"Severity": "low",
|
||||
"ResourceType": "AwsEc2SecurityGroup",
|
||||
"Description": "Extended Description",
|
||||
"Risk": "If Security groups are not properly configured the attack surface is increased.",
|
||||
"RelatedUrl": "https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "cli command or URL to the cli command location.",
|
||||
"NativeIaC": "code or URL to the code location.",
|
||||
"Other": "cli command or URL to the cli command location.",
|
||||
"Terraform": "code or URL to the code location."
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Use a Zero Trust approach. Narrow ingress traffic as much as possible. Consider north-south as well as east-west traffic.",
|
||||
"Url": "https://docs.aws.amazon.com/vpc/latest/userguide/vpc-security-best-practices.html"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"cat1",
|
||||
"cat2"
|
||||
],
|
||||
"Tags": {
|
||||
"Tag1Key": "value",
|
||||
"Tag2Key": "value"
|
||||
},
|
||||
"DependsOn": [
|
||||
"othercheck1",
|
||||
"othercheck2"
|
||||
],
|
||||
"RelatedTo": [
|
||||
"othercheck3",
|
||||
"othercheck4"
|
||||
],
|
||||
"Notes": "additional information"
|
||||
}
|
||||
398
contrib/codebuild/codebuild-prowlerv3-audit-account-cfn.yaml
Normal file
@@ -0,0 +1,398 @@
|
||||
---
|
||||
AWSTemplateFormatVersion: 2010-09-09
|
||||
Description: Creates a CodeBuild project to audit an AWS account with Prowler Version 2 and stores the html report in a S3 bucket. This will run onece at the beginning and on a schedule afterwards. Partial contribution from https://github.com/stevecjones
|
||||
Parameters:
|
||||
ServiceName:
|
||||
Description: 'Specifies the service name used within component naming'
|
||||
Type: String
|
||||
Default: 'prowler'
|
||||
|
||||
LogsRetentionInDays:
|
||||
Description: 'Specifies the number of days you want to retain CodeBuild run log events in the specified log group. Junit reports are kept for 30 days, HTML reports in S3 are not deleted'
|
||||
Type: Number
|
||||
Default: 3
|
||||
AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 180, 365]
|
||||
|
||||
ProwlerOptions:
|
||||
Description: 'Options to pass to Prowler command, use -f to filter specific regions, -c for specific checks, -s for specific services, for SecurityHub integration use "-f shub_region -S", for more options see -h. For a complete assessment leave this empty.'
|
||||
Type: String
|
||||
# Prowler command below runs a set of checks, configure it base on your needs, no options will run all regions all checks.
|
||||
Default: -f eu-west-1 -s s3 iam ec2
|
||||
|
||||
ProwlerScheduler:
|
||||
Description: The time when Prowler will run in cron format. Default is daily at 22:00h or 10PM 'cron(0 22 * * ? *)', for every 5 hours also works 'rate(5 hours)'. More info here https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html.
|
||||
Type: String
|
||||
Default: 'cron(0 22 * * ? *)'
|
||||
|
||||
Resources:
|
||||
CodeBuildStartBuild:
|
||||
Type: 'Custom::CodeBuildStartBuild'
|
||||
DependsOn:
|
||||
- CodeBuildLogPolicy
|
||||
- CodeBuildStartLogPolicy
|
||||
Properties:
|
||||
Build: !Ref ProwlerCodeBuild
|
||||
ServiceToken: !GetAtt CodeBuildStartBuildLambda.Arn
|
||||
|
||||
CodeBuildStartBuildLambdaRole:
|
||||
Type: 'AWS::IAM::Role'
|
||||
Properties:
|
||||
AssumeRolePolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Service: !Sub lambda.${AWS::URLSuffix}
|
||||
Action: 'sts:AssumeRole'
|
||||
Description: !Sub 'DO NOT DELETE - Used by Lambda. Created by CloudFormation Stack ${AWS::StackId}'
|
||||
Policies:
|
||||
- PolicyName: StartBuildInline
|
||||
PolicyDocument:
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action: 'codebuild:StartBuild'
|
||||
Resource: !GetAtt ProwlerCodeBuild.Arn
|
||||
|
||||
CodeBuildStartBuildLambda:
|
||||
Type: 'AWS::Lambda::Function'
|
||||
Metadata:
|
||||
cfn_nag:
|
||||
rules_to_suppress:
|
||||
- id: W58
|
||||
reason: 'This Lambda has permissions to write Logs'
|
||||
- id: W89
|
||||
reason: 'VPC is not needed'
|
||||
- id: W92
|
||||
reason: 'ReservedConcurrentExecutions not needed'
|
||||
Properties:
|
||||
Handler: index.lambda_handler
|
||||
MemorySize: 128
|
||||
Role: !Sub ${CodeBuildStartBuildLambdaRole.Arn}
|
||||
Timeout: 120
|
||||
Runtime: python3.9
|
||||
Code:
|
||||
ZipFile: |
|
||||
import boto3
|
||||
import cfnresponse
|
||||
from botocore.exceptions import ClientError
|
||||
|
||||
def lambda_handler(event,context):
|
||||
props = event['ResourceProperties']
|
||||
codebuild_client = boto3.client('codebuild')
|
||||
|
||||
if (event['RequestType'] == 'Create' or event['RequestType'] == 'Update'):
|
||||
try:
|
||||
response = codebuild_client.start_build(projectName=props['Build'])
|
||||
print(response)
|
||||
print("Respond: SUCCESS")
|
||||
cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
|
||||
except Exception as ex:
|
||||
print(ex.response['Error']['Message'])
|
||||
cfnresponse.send(event, context, cfnresponse.FAILED, ex.response)
|
||||
else:
|
||||
cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
|
||||
|
||||
CodeBuildStartLogGroup:
|
||||
Type: 'AWS::Logs::LogGroup'
|
||||
DeletionPolicy: Delete
|
||||
UpdateReplacePolicy: Delete
|
||||
Metadata:
|
||||
cfn_nag:
|
||||
rules_to_suppress:
|
||||
- id: W84
|
||||
reason: 'KMS encryption is not needed.'
|
||||
Properties:
|
||||
LogGroupName: !Sub '/aws/lambda/${CodeBuildStartBuildLambda}'
|
||||
RetentionInDays: !Ref LogsRetentionInDays
|
||||
|
||||
CodeBuildStartLogPolicy:
|
||||
Type: AWS::IAM::Policy
|
||||
Properties:
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action:
|
||||
- logs:CreateLogStream
|
||||
- logs:PutLogEvents
|
||||
Effect: Allow
|
||||
Resource: !GetAtt CodeBuildStartLogGroup.Arn
|
||||
PolicyName: LogGroup
|
||||
Roles:
|
||||
- !Ref CodeBuildStartBuildLambdaRole
|
||||
|
||||
ArtifactBucket:
|
||||
Type: AWS::S3::Bucket
|
||||
Metadata:
|
||||
cfn_nag:
|
||||
rules_to_suppress:
|
||||
- id: W35
|
||||
reason: 'S3 Access Logging is not needed'
|
||||
Properties:
|
||||
Tags:
|
||||
- Key: Name
|
||||
Value: !Sub '${ServiceName}-${AWS::AccountId}-S3-Prowler-${AWS::StackName}'
|
||||
BucketName: !Sub '${ServiceName}-reports-${AWS::Region}-prowler-${AWS::AccountId}'
|
||||
AccessControl: LogDeliveryWrite
|
||||
VersioningConfiguration:
|
||||
Status: Enabled
|
||||
BucketEncryption:
|
||||
ServerSideEncryptionConfiguration:
|
||||
- ServerSideEncryptionByDefault:
|
||||
SSEAlgorithm: AES256
|
||||
PublicAccessBlockConfiguration:
|
||||
BlockPublicAcls: true
|
||||
BlockPublicPolicy: true
|
||||
IgnorePublicAcls: true
|
||||
RestrictPublicBuckets: true
|
||||
|
||||
ArtifactBucketPolicy:
|
||||
Type: AWS::S3::BucketPolicy
|
||||
Properties:
|
||||
Bucket: !Ref ArtifactBucket
|
||||
PolicyDocument:
|
||||
Id: Content
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action: '*'
|
||||
Condition:
|
||||
Bool:
|
||||
aws:SecureTransport: false
|
||||
Effect: Deny
|
||||
Principal: '*'
|
||||
Resource: !Sub '${ArtifactBucket.Arn}/*'
|
||||
Sid: S3ForceSSL
|
||||
- Action: 's3:PutObject'
|
||||
Condition:
|
||||
'Null':
|
||||
s3:x-amz-server-side-encryption: true
|
||||
Effect: Deny
|
||||
Principal: '*'
|
||||
Resource: !Sub '${ArtifactBucket.Arn}/*'
|
||||
Sid: DenyUnEncryptedObjectUploads
|
||||
|
||||
CodeBuildServiceRole:
|
||||
Type: AWS::IAM::Role
|
||||
Metadata:
|
||||
cfn_nag:
|
||||
rules_to_suppress:
|
||||
- id: W11
|
||||
reason: 'Role complies with the least privilege principle.'
|
||||
Properties:
|
||||
Description: !Sub 'DO NOT DELETE - Used by CodeBuild. Created by CloudFormation Stack ${AWS::StackId}'
|
||||
ManagedPolicyArns:
|
||||
- !Sub 'arn:${AWS::Partition}:iam::aws:policy/job-function/SupportUser'
|
||||
- !Sub 'arn:${AWS::Partition}:iam::aws:policy/job-function/ViewOnlyAccess'
|
||||
- !Sub 'arn:${AWS::Partition}:iam::aws:policy/SecurityAudit'
|
||||
AssumeRolePolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action: 'sts:AssumeRole'
|
||||
Effect: Allow
|
||||
Principal:
|
||||
Service: !Sub codebuild.${AWS::URLSuffix}
|
||||
Policies:
|
||||
- PolicyName: S3
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action:
|
||||
- s3:PutObject
|
||||
- s3:GetObject
|
||||
- s3:GetObjectVersion
|
||||
- s3:GetBucketAcl
|
||||
- s3:GetBucketLocation
|
||||
Effect: Allow
|
||||
Resource: !Sub '${ArtifactBucket.Arn}/*'
|
||||
- PolicyName: ProwlerAdditions
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action:
|
||||
- account:Get*
|
||||
- appstream:Describe*
|
||||
- codeartifact:List*
|
||||
- codebuild:BatchGet*
|
||||
- ds:Get*
|
||||
- ds:Describe*
|
||||
- ds:List*
|
||||
- ec2:GetEbsEncryptionByDefault
|
||||
- ecr:Describe*
|
||||
- elasticfilesystem:DescribeBackupPolicy
|
||||
- glue:GetConnections
|
||||
- glue:GetSecurityConfiguration*
|
||||
- glue:SearchTables
|
||||
- lambda:GetFunction*
|
||||
- macie2:GetMacieSession
|
||||
- s3:GetAccountPublicAccessBlock
|
||||
- s3:GetPublicAccessBlock
|
||||
- shield:DescribeProtection
|
||||
- shield:GetSubscriptionState
|
||||
- securityhub:BatchImportFindings
|
||||
- securityhub:GetFindings
|
||||
- ssm:GetDocument
|
||||
- support:Describe*
|
||||
- tag:GetTagKeys
|
||||
Effect: Allow
|
||||
Resource: '*'
|
||||
- PolicyName: ProwlerAdditionsApiGW
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action:
|
||||
- apigateway:GET
|
||||
Effect: Allow
|
||||
Resource: 'arn:aws:apigateway:*::/restapis/*'
|
||||
- PolicyName: CodeBuild
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action:
|
||||
- codebuild:CreateReportGroup
|
||||
- codebuild:CreateReport
|
||||
- codebuild:UpdateReport
|
||||
- codebuild:BatchPutTestCases
|
||||
- codebuild:BatchPutCodeCoverages
|
||||
Effect: Allow
|
||||
Resource: !Sub 'arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/*'
|
||||
- PolicyName: SecurityHubBatchImportFindings
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action: securityhub:BatchImportFindings
|
||||
Effect: Allow
|
||||
Resource: !Sub 'arn:${AWS::Partition}:securityhub:${AWS::Region}::product/prowler/prowler'
|
||||
|
||||
CodeBuildLogPolicy:
|
||||
Type: AWS::IAM::Policy
|
||||
Properties:
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action:
|
||||
- logs:CreateLogStream
|
||||
- logs:PutLogEvents
|
||||
Effect: Allow
|
||||
Resource: !GetAtt ProwlerLogGroup.Arn
|
||||
PolicyName: LogGroup
|
||||
Roles:
|
||||
- !Ref CodeBuildServiceRole
|
||||
|
||||
CodeBuildAssumePolicy:
|
||||
Type: AWS::IAM::Policy
|
||||
Properties:
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action: 'sts:AssumeRole'
|
||||
Effect: Allow
|
||||
Resource: !GetAtt CodeBuildServiceRole.Arn
|
||||
PolicyName: AssumeRole
|
||||
Roles:
|
||||
- !Ref CodeBuildServiceRole
|
||||
|
||||
ProwlerCodeBuild:
|
||||
Type: AWS::CodeBuild::Project
|
||||
Metadata:
|
||||
cfn_nag:
|
||||
rules_to_suppress:
|
||||
- id: W32
|
||||
reason: 'KMS encryption is not needed.'
|
||||
Properties:
|
||||
Artifacts:
|
||||
Type: NO_ARTIFACTS
|
||||
ConcurrentBuildLimit: 1
|
||||
Source:
|
||||
Type: NO_SOURCE
|
||||
BuildSpec: |
|
||||
version: 0.2
|
||||
phases:
|
||||
install:
|
||||
runtime-versions:
|
||||
python: 3.9
|
||||
commands:
|
||||
- echo "Installing Prowler..."
|
||||
- pip3 install prowler
|
||||
build:
|
||||
commands:
|
||||
- echo "Running Prowler as prowler $PROWLER_OPTIONS"
|
||||
- prowler $PROWLER_OPTIONS
|
||||
post_build:
|
||||
commands:
|
||||
- echo "Uploading reports to S3..."
|
||||
- aws s3 cp --sse AES256 output/ s3://$BUCKET_REPORT/ --recursive
|
||||
- echo "Done!"
|
||||
# Currently not supported in Version 3
|
||||
# reports:
|
||||
# prowler:
|
||||
# files:
|
||||
# - '**/*'
|
||||
# base-directory: 'junit-reports'
|
||||
# file-format: JunitXml
|
||||
Environment:
|
||||
# AWS CodeBuild free tier includes 100 build minutes of BUILD_GENERAL1_SMALL per month.
|
||||
# BUILD_GENERAL1_SMALL: Use up to 3 GB memory and 2 vCPUs for builds. $0.005/minute.
|
||||
# BUILD_GENERAL1_MEDIUM: Use up to 7 GB memory and 4 vCPUs for builds. $0.01/minute.
|
||||
# BUILD_GENERAL1_LARGE: Use up to 15 GB memory and 8 vCPUs for builds. $0.02/minute.
|
||||
# BUILD_GENERAL1_2XLARGE: Use up to 144 GB memory and 72 vCPUs for builds. $0.20/minute.
|
||||
ComputeType: "BUILD_GENERAL1_SMALL"
|
||||
Image: "aws/codebuild/amazonlinux2-x86_64-standard:3.0"
|
||||
Type: "LINUX_CONTAINER"
|
||||
EnvironmentVariables:
|
||||
- Name: BUCKET_REPORT
|
||||
Value: !Ref ArtifactBucket
|
||||
Type: PLAINTEXT
|
||||
- Name: PROWLER_OPTIONS
|
||||
Value: !Ref ProwlerOptions
|
||||
Type: PLAINTEXT
|
||||
Description: Run Prowler assessment
|
||||
ServiceRole: !GetAtt CodeBuildServiceRole.Arn
|
||||
TimeoutInMinutes: 300
|
||||
|
||||
ProwlerLogGroup:
|
||||
Type: 'AWS::Logs::LogGroup'
|
||||
DeletionPolicy: Delete
|
||||
UpdateReplacePolicy: Delete
|
||||
Metadata:
|
||||
cfn_nag:
|
||||
rules_to_suppress:
|
||||
- id: W84
|
||||
reason: 'KMS encryption is not needed.'
|
||||
Properties:
|
||||
LogGroupName: !Sub '/aws/codebuild/${ProwlerCodeBuild}'
|
||||
RetentionInDays: !Ref LogsRetentionInDays
|
||||
|
||||
EventBridgeServiceRole:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
Description: !Sub 'DO NOT DELETE - Used by EventBridge. Created by CloudFormation Stack ${AWS::StackId}'
|
||||
AssumeRolePolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action: 'sts:AssumeRole'
|
||||
Effect: Allow
|
||||
Principal:
|
||||
Service: !Sub events.${AWS::URLSuffix}
|
||||
Policies:
|
||||
- PolicyName: CodeBuild
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action: 'codebuild:StartBuild'
|
||||
Resource: !GetAtt ProwlerCodeBuild.Arn
|
||||
|
||||
ProwlerSchedule:
|
||||
Type: 'AWS::Events::Rule'
|
||||
Properties:
|
||||
Description: A schedule to trigger Prowler in CodeBuild
|
||||
ScheduleExpression: !Ref ProwlerScheduler
|
||||
State: ENABLED
|
||||
Targets:
|
||||
- Arn: !GetAtt ProwlerCodeBuild.Arn
|
||||
Id: ProwlerSchedule
|
||||
RoleArn: !GetAtt EventBridgeServiceRole.Arn
|
||||
|
||||
Outputs:
|
||||
ArtifactBucketName:
|
||||
Description: Artifact Bucket Name
|
||||
Value: !Ref ArtifactBucket
|
||||
@@ -1,45 +1,24 @@
|
||||
# Build command
|
||||
# docker build --platform=linux/amd64 --no-cache -t prowler:latest .
|
||||
|
||||
FROM public.ecr.aws/amazonlinux/amazonlinux:2022
|
||||
ARG PROWLER_VERSION=latest
|
||||
|
||||
ARG PROWLERVER=2.9.0
|
||||
ARG USERNAME=prowler
|
||||
ARG USERID=34000
|
||||
FROM toniblyx/prowler:${PROWLER_VERSION}
|
||||
|
||||
# Install Dependencies
|
||||
RUN \
|
||||
dnf update -y && \
|
||||
dnf install -y bash file findutils git jq python3 python3-pip \
|
||||
python3-setuptools python3-wheel shadow-utils tar unzip which && \
|
||||
dnf remove -y awscli && \
|
||||
dnf clean all && \
|
||||
useradd -l -s /bin/sh -U -u ${USERID} ${USERNAME} && \
|
||||
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
|
||||
unzip awscliv2.zip && \
|
||||
./aws/install && \
|
||||
pip3 install --no-cache-dir --upgrade pip && \
|
||||
pip3 install --no-cache-dir "git+https://github.com/ibm/detect-secrets.git@master#egg=detect-secrets" && \
|
||||
rm -rf aws awscliv2.zip /var/cache/dnf
|
||||
USER 0
|
||||
# hadolint ignore=DL3018
|
||||
RUN apk --no-cache add bash aws-cli jq
|
||||
|
||||
# Place script and env vars
|
||||
COPY .awsvariables run-prowler-securityhub.sh /
|
||||
ARG MULTI_ACCOUNT_SECURITY_HUB_PATH=/home/prowler/multi-account-securityhub
|
||||
|
||||
# Installs prowler and change permissions
|
||||
RUN \
|
||||
curl -L "https://github.com/prowler-cloud/prowler/archive/refs/tags/${PROWLERVER}.tar.gz" -o "prowler.tar.gz" && \
|
||||
tar xvzf prowler.tar.gz && \
|
||||
rm -f prowler.tar.gz && \
|
||||
mv prowler-${PROWLERVER} prowler && \
|
||||
chown ${USERNAME}:${USERNAME} /run-prowler-securityhub.sh && \
|
||||
chmod 500 /run-prowler-securityhub.sh && \
|
||||
chown ${USERNAME}:${USERNAME} /.awsvariables && \
|
||||
chmod 400 /.awsvariables && \
|
||||
chown ${USERNAME}:${USERNAME} -R /prowler && \
|
||||
chmod +x /prowler/prowler
|
||||
USER prowler
|
||||
|
||||
# Drop to user
|
||||
USER ${USERNAME}
|
||||
# Move script and environment variables
|
||||
RUN mkdir "${MULTI_ACCOUNT_SECURITY_HUB_PATH}"
|
||||
COPY --chown=prowler:prowler .awsvariables run-prowler-securityhub.sh "${MULTI_ACCOUNT_SECURITY_HUB_PATH}"/
|
||||
RUN chmod 500 "${MULTI_ACCOUNT_SECURITY_HUB_PATH}"/run-prowler-securityhub.sh & \
|
||||
chmod 400 "${MULTI_ACCOUNT_SECURITY_HUB_PATH}"/.awsvariables
|
||||
|
||||
# Run script
|
||||
ENTRYPOINT ["/run-prowler-securityhub.sh"]
|
||||
WORKDIR ${MULTI_ACCOUNT_SECURITY_HUB_PATH}
|
||||
|
||||
ENTRYPOINT ["./run-prowler-securityhub.sh"]
|
||||
|
||||
51
contrib/multi-account-securityhub/run-prowler-securityhub.sh
Normal file → Executable file
@@ -1,20 +1,17 @@
|
||||
#!/bin/bash
|
||||
# Run Prowler against All AWS Accounts in an AWS Organization
|
||||
|
||||
# Change Directory (rest of the script, assumes you're in the root directory)
|
||||
cd / || exit
|
||||
|
||||
# Show Prowler Version
|
||||
./prowler/prowler -V
|
||||
prowler -v
|
||||
|
||||
# Source .awsvariables
|
||||
# shellcheck disable=SC1091
|
||||
source .awsvariables
|
||||
|
||||
# Get Values from Environment Variables
|
||||
echo "ROLE: $ROLE"
|
||||
echo "PARALLEL_ACCOUNTS: $PARALLEL_ACCOUNTS"
|
||||
echo "REGION: $REGION"
|
||||
echo "ROLE: ${ROLE}"
|
||||
echo "PARALLEL_ACCOUNTS: ${PARALLEL_ACCOUNTS}"
|
||||
echo "REGION: ${REGION}"
|
||||
|
||||
# Function to unset AWS Profile Variables
|
||||
unset_aws() {
|
||||
@@ -24,33 +21,33 @@ unset_aws
|
||||
|
||||
# Find THIS Account AWS Number
|
||||
CALLER_ARN=$(aws sts get-caller-identity --output text --query "Arn")
|
||||
PARTITION=$(echo "$CALLER_ARN" | cut -d: -f2)
|
||||
THISACCOUNT=$(echo "$CALLER_ARN" | cut -d: -f5)
|
||||
echo "THISACCOUNT: $THISACCOUNT"
|
||||
echo "PARTITION: $PARTITION"
|
||||
PARTITION=$(echo "${CALLER_ARN}" | cut -d: -f2)
|
||||
THISACCOUNT=$(echo "${CALLER_ARN}" | cut -d: -f5)
|
||||
echo "THISACCOUNT: ${THISACCOUNT}"
|
||||
echo "PARTITION: ${PARTITION}"
|
||||
|
||||
# Function to Assume Role to THIS Account & Create Session
|
||||
this_account_session() {
|
||||
unset_aws
|
||||
role_credentials=$(aws sts assume-role --role-arn arn:"$PARTITION":iam::"$THISACCOUNT":role/"$ROLE" --role-session-name ProwlerRun --output json)
|
||||
AWS_ACCESS_KEY_ID=$(echo "$role_credentials" | jq -r .Credentials.AccessKeyId)
|
||||
AWS_SECRET_ACCESS_KEY=$(echo "$role_credentials" | jq -r .Credentials.SecretAccessKey)
|
||||
AWS_SESSION_TOKEN=$(echo "$role_credentials" | jq -r .Credentials.SessionToken)
|
||||
role_credentials=$(aws sts assume-role --role-arn arn:"${PARTITION}":iam::"${THISACCOUNT}":role/"${ROLE}" --role-session-name ProwlerRun --output json)
|
||||
AWS_ACCESS_KEY_ID=$(echo "${role_credentials}" | jq -r .Credentials.AccessKeyId)
|
||||
AWS_SECRET_ACCESS_KEY=$(echo "${role_credentials}" | jq -r .Credentials.SecretAccessKey)
|
||||
AWS_SESSION_TOKEN=$(echo "${role_credentials}" | jq -r .Credentials.SessionToken)
|
||||
export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
|
||||
}
|
||||
|
||||
# Find AWS Master Account
|
||||
this_account_session
|
||||
AWSMASTER=$(aws organizations describe-organization --query Organization.MasterAccountId --output text)
|
||||
echo "AWSMASTER: $AWSMASTER"
|
||||
echo "AWSMASTER: ${AWSMASTER}"
|
||||
|
||||
# Function to Assume Role to Master Account & Create Session
|
||||
master_account_session() {
|
||||
unset_aws
|
||||
role_credentials=$(aws sts assume-role --role-arn arn:"$PARTITION":iam::"$AWSMASTER":role/"$ROLE" --role-session-name ProwlerRun --output json)
|
||||
AWS_ACCESS_KEY_ID=$(echo "$role_credentials" | jq -r .Credentials.AccessKeyId)
|
||||
AWS_SECRET_ACCESS_KEY=$(echo "$role_credentials" | jq -r .Credentials.SecretAccessKey)
|
||||
AWS_SESSION_TOKEN=$(echo "$role_credentials" | jq -r .Credentials.SessionToken)
|
||||
role_credentials=$(aws sts assume-role --role-arn arn:"${PARTITION}":iam::"${AWSMASTER}":role/"${ROLE}" --role-session-name ProwlerRun --output json)
|
||||
AWS_ACCESS_KEY_ID=$(echo "${role_credentials}" | jq -r .Credentials.AccessKeyId)
|
||||
AWS_SECRET_ACCESS_KEY=$(echo "${role_credentials}" | jq -r .Credentials.SecretAccessKey)
|
||||
AWS_SESSION_TOKEN=$(echo "${role_credentials}" | jq -r .Credentials.SessionToken)
|
||||
export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
|
||||
}
|
||||
|
||||
@@ -60,20 +57,20 @@ ACCOUNTS_IN_ORGS=$(aws organizations list-accounts --query Accounts[*].Id --outp
|
||||
|
||||
# Run Prowler against Accounts in AWS Organization
|
||||
echo "AWS Accounts in Organization"
|
||||
echo "$ACCOUNTS_IN_ORGS"
|
||||
for accountId in $ACCOUNTS_IN_ORGS; do
|
||||
echo "${ACCOUNTS_IN_ORGS}"
|
||||
for accountId in ${ACCOUNTS_IN_ORGS}; do
|
||||
# shellcheck disable=SC2015
|
||||
test "$(jobs | wc -l)" -ge $PARALLEL_ACCOUNTS && wait -n || true
|
||||
test "$(jobs | wc -l)" -ge "${PARALLEL_ACCOUNTS}" && wait -n || true
|
||||
{
|
||||
START_TIME=$SECONDS
|
||||
START_TIME=${SECONDS}
|
||||
# Unset AWS Profile Variables
|
||||
unset_aws
|
||||
# Run Prowler
|
||||
echo -e "Assessing AWS Account: $accountId, using Role: $ROLE on $(date)"
|
||||
echo -e "Assessing AWS Account: ${accountId}, using Role: ${ROLE} on $(date)"
|
||||
# Pipe stdout to /dev/null to reduce unnecessary Cloudwatch logs
|
||||
./prowler/prowler -R "$ROLE" -A "$accountId" -M json-asff -q -S -f "$REGION" > /dev/null
|
||||
prowler aws -R arn:"${PARTITION}":iam::"${accountId}":role/"${ROLE}" -q -S -f "${REGION}" > /dev/null
|
||||
TOTAL_SEC=$((SECONDS - START_TIME))
|
||||
printf "Completed AWS Account: $accountId in %02dh:%02dm:%02ds" $((TOTAL_SEC / 3600)) $((TOTAL_SEC % 3600 / 60)) $((TOTAL_SEC % 60))
|
||||
printf "Completed AWS Account: ${accountId} in %02dh:%02dm:%02ds" $((TOTAL_SEC / 3600)) $((TOTAL_SEC % 3600 / 60)) $((TOTAL_SEC % 60))
|
||||
echo ""
|
||||
} &
|
||||
done
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Organizational Prowler with Serverless
|
||||
|
||||
Langage: [Korean](README_kr.md)
|
||||
Language: [Korean](README_kr.md)
|
||||
|
||||
This project is created to apply prowler in a multi-account environment within AWS Organizations.
|
||||
CloudWatch triggers CodeBuild every fixed time.
|
||||
@@ -18,12 +18,12 @@ For more information on how to use prowler, see [here](https://github.com/prowle
|
||||
2. **Master Account**
|
||||
1. Deploy [ProwlerRole.yaml](templates/ProwlerRole.yaml) stack to CloudFormation in a bid to create resources to master account itself.
|
||||
(The template will be also deployed for other member accounts as a StackSet)
|
||||
- ProwlerCodeBuildAccount : Audit Acccount ID where CodeBuild resides. (preferably Audit/Security account)
|
||||
- ProwlerCodeBuildAccount : Audit Account ID where CodeBuild resides. (preferably Audit/Security account)
|
||||
- ProwlerCodeBuildRole : Role name to use in CodeBuild service
|
||||
- ProwlerCrossAccountRole : Role name to assume for Cross account
|
||||
- ProwlerS3 : The S3 bucket name where reports will be put
|
||||
1. Create **StackSet** with [ProwlerRole.yaml](templates/ProwlerRole.yaml) to deploy Role into member accounts in AWS Organizations.
|
||||
- ProwlerCodeBuildAccount : Audit Acccount ID where CodeBuild resides. (preferably Audit/Security account)
|
||||
- ProwlerCodeBuildAccount : Audit Account ID where CodeBuild resides. (preferably Audit/Security account)
|
||||
- ProwlerCodeBuildRole : Role name to use in CodeBuild service
|
||||
- ProwlerCrossAccountRole : Role name to assume for Cross account
|
||||
- ProwlerS3 : The S3 bucket name where reports will be put
|
||||
@@ -45,4 +45,4 @@ For more information on how to use prowler, see [here](https://github.com/prowle
|
||||
- ProwlerReportS3Account : The account where the report S3 bucket resides.
|
||||
1. If you'd like to change the scheduled time,
|
||||
1. You can change the cron expression of ScheduleExpression within [ProwlerCodeBuildStack.yaml](templates/ProwlerCodeBuildStack.yaml).
|
||||
2. Alternatively, you can make changes directrly from Events > Rules > ProwlerExecuteRule > Actions > Edit in CloudWatch console.
|
||||
2. Alternatively, you can make changes directly from Events > Rules > ProwlerExecuteRule > Actions > Edit in CloudWatch console.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Organizational Prowler with Serverless
|
||||
|
||||
Langage: [English](README.md)
|
||||
Language: [English](README.md)
|
||||
|
||||
이 문서는 AWS Organization 내의 multi account 환경에서 prowler 를 적용하기 위해 작성된 문서입니다.
|
||||
일정 시간마다 CloudWatch는 CodeBuild 를 트리거합니다.
|
||||
@@ -22,7 +22,7 @@ prowler 의 자세한 사용방법은 [이 곳](https://github.com/prowler-cloud
|
||||
|
||||
[ProwlerRole.yaml](templates/ProwlerRole.yaml)
|
||||
|
||||
- ProwlerCodeBuildAccount : CodeBuild 가 있는 Audit Acccount ID
|
||||
- ProwlerCodeBuildAccount : CodeBuild 가 있는 Audit Account ID
|
||||
- ProwlerCodeBuildRole : CodeBuild의 생성될 Role 이름
|
||||
- ProwlerCrossAccountRole : Cross account 용 Assume할 Role 이름
|
||||
- ProwlerS3 : report 가 저장될 S3 bucket 명
|
||||
@@ -30,7 +30,7 @@ prowler 의 자세한 사용방법은 [이 곳](https://github.com/prowler-cloud
|
||||
|
||||
[ProwlerRole.yaml](templates/ProwlerRole.yaml)
|
||||
|
||||
- ProwlerCodeBuildAccount : CodeBuild 가 있는 Audit Acccount
|
||||
- ProwlerCodeBuildAccount : CodeBuild 가 있는 Audit Account
|
||||
- ProwlerCodeBuildRole : CodeBuild에서 사용할 Role 이름
|
||||
- ProwlerCrossAccountRole : Cross account 용 Assume할 Role 이름
|
||||
- ProwlerS3 : report 가 저장될 S3 bucket 명
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
The following demonstartes how to quickly install the resources necessary to perform a security baseline using Prowler. The speed is based on the prebuilt terraform module that can configure all the resources necessuary to run Prowler with the findings being sent to AWS Security Hub.
|
||||
The following demonstrates how to quickly install the resources necessary to perform a security baseline using Prowler. The speed is based on the prebuilt terraform module that can configure all the resources necessary to run Prowler with the findings being sent to AWS Security Hub.
|
||||
|
||||
## Install
|
||||
|
||||
@@ -24,7 +24,7 @@ Installing Prowler with Terraform is simple and can be completed in under 1 minu
|
||||
|
||||

|
||||
|
||||
- It is likely an error will return related to the SecurityHub subscription. This appears to be Terraform related and you can validate the configuration by navigating to the SecurityHub console. Click Integreations and search for Prowler. Take note of the green check where it says *Accepting findings*
|
||||
- It is likely an error will return related to the SecurityHub subscription. This appears to be Terraform related and you can validate the configuration by navigating to the SecurityHub console. Click Integrations and search for Prowler. Take note of the green check where it says *Accepting findings*
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ To make sure rules are working fine, run `/var/ossec/bin/ossec-logtest` and copy
|
||||
```
|
||||
You must see 3 phases goin on.
|
||||
|
||||
To check if there is any error you can enable the debug mode of `modulesd` setting the `wazuh_modules.debug=0` variable to 2 in `/var/ossec/etc/internal_options.conf` file. Restart wazun-manager and errors should appear in the `/var/ossec/logs/ossec.log` file.
|
||||
To check if there is any error you can enable the debug mode of `modulesd` setting the `wazuh_modules.debug=0` variable to 2 in `/var/ossec/etc/internal_options.conf` file. Restart wazuh-manager and errors should appear in the `/var/ossec/logs/ossec.log` file.
|
||||
|
||||
## Thanks
|
||||
|
||||
|
||||
@@ -5,20 +5,20 @@ hide:
|
||||
# About
|
||||
|
||||
## Author
|
||||
Prowler was created by **Toni de la Fuente** in 2016.
|
||||
Prowler was created by **Toni de la Fuente** in 2016.
|
||||
|
||||
| <br>[](https://twitter.com/toniblyx) [](https://twitter.com/prowlercloud)|
|
||||
| <br>[](https://twitter.com/toniblyx) [](https://twitter.com/prowlercloud)|
|
||||
|:--:|
|
||||
| <b>Toni de la Fuente </b>|
|
||||
|
||||
## Maintainers
|
||||
Prowler is maintained by the Engineers of the **Prowler Team** :
|
||||
|
||||
| [](https://twitter.com/NachoRivCor) | [](https://twitter.com/sergargar1) |[](https://twitter.com/jfagoagas) |
|
||||
| [](https://twitter.com/NachoRivCor) | [](https://twitter.com/sergargar1) |[](https://twitter.com/jfagoagas) |
|
||||
|:--:|:--:|:--:
|
||||
| <b>Nacho Rivera</b>| <b>Sergio Garcia</b>| <b>Pepe Fagoaga</b>|
|
||||
|
||||
## License
|
||||
|
||||
Prowler is licensed as **Apache License 2.0** as specified in each file. You may obtain a copy of the License at
|
||||
<http://www.apache.org/licenses/LICENSE-2.0>
|
||||
<http://www.apache.org/licenses/LICENSE-2.0>
|
||||
|
||||
9
docs/developer-guide/audit-info.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Audit Info
|
||||
|
||||
In each Prowler provider we have a Python object called `audit_info` which is in charge of keeping the credentials, the configuration and the state of each audit, and it's passed to each service during the `__init__`.
|
||||
|
||||
- AWS: https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/aws/lib/audit_info/models.py#L34-L54
|
||||
- GCP: https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/aws/lib/audit_info/models.py#L7-L30
|
||||
- Azure: https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/azure/lib/audit_info/models.py#L17-L31
|
||||
|
||||
This `audit_info` object is shared during the Prowler execution and for that reason is important to mock it in each test to isolate them. See the [testing guide](./unit-testing.md) for more information.
|
||||
309
docs/developer-guide/checks.md
Normal file
@@ -0,0 +1,309 @@
|
||||
# Create a new Check for a Provider
|
||||
|
||||
Here you can find how to create new checks for Prowler.
|
||||
|
||||
**To create a check is required to have a Prowler provider service already created, so if the service is not present or the attribute you want to audit is not retrieved by the service, please refer to the [Service](./services.md) documentation.**
|
||||
|
||||
## Introduction
|
||||
To create a new check for a supported Prowler provider, you will need to create a folder with the check name inside the specific service for the selected provider.
|
||||
|
||||
We are going to use the `ec2_ami_public` check form the `AWS` provider as an example. So the folder name will `prowler/providers/aws/services/ec2/ec2_ami_public` (following the format `prowler/providers/<provider>/services/<service>/<check_name>`), with the name of check following the pattern: `service_subservice/resource_action`.
|
||||
|
||||
Inside that folder, we need to create three files:
|
||||
|
||||
- An empty `__init__.py`: to make Python treat this check folder as a package.
|
||||
- A `check_name.py` with the above format containing the check's logic. Refer to the [check](./checks.md#check)
|
||||
- A `check_name.metadata.json` containing the check's metadata. Refer to the [check metadata](./checks.md#check-metadata)
|
||||
|
||||
## Check
|
||||
|
||||
The Prowler's check structure is very simple and following it there is nothing more to do to include a check in a provider's service because the load is done dynamically based on the paths.
|
||||
|
||||
The following is the code for the `ec2_ami_public` check:
|
||||
```python title="Check Class"
|
||||
# At the top of the file we need to import the following:
|
||||
# - Check class which is in charge of the following:
|
||||
# - Retrieve the check metadata and expose the `metadata()`
|
||||
# to return a JSON representation of the metadata,
|
||||
# read more at Check Metadata Model down below.
|
||||
# - Enforce that each check requires to have the `execute()` function
|
||||
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||
|
||||
# Then you have to import the provider service client
|
||||
# read more at the Service documentation.
|
||||
from prowler.providers.aws.services.ec2.ec2_client import ec2_client
|
||||
|
||||
# For each check we need to create a python class called the same as the
|
||||
# file which inherits from the Check class.
|
||||
class ec2_ami_public(Check):
|
||||
"""ec2_ami_public verifies if an EC2 AMI is publicly shared"""
|
||||
|
||||
# Then, within the check's class we need to create the "execute(self)"
|
||||
# function, which is enforce by the "Check" class to implement
|
||||
# the Check's interface and let Prowler to run this check.
|
||||
def execute(self):
|
||||
|
||||
# Inside the execute(self) function we need to create
|
||||
# the list of findings initialised to an empty list []
|
||||
findings = []
|
||||
|
||||
# Then, using the service client we need to iterate by the resource we
|
||||
# want to check, in this case EC2 AMIs stored in the
|
||||
# "ec2_client.images" object.
|
||||
for image in ec2_client.images:
|
||||
|
||||
# Once iterating for the images, we have to intialise
|
||||
# the Check_Report_AWS class passing the check's metadata
|
||||
# using the "metadata" function explained above.
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
|
||||
# For each Prowler check we MUST fill the following
|
||||
# Check_Report_AWS fields:
|
||||
# - region
|
||||
# - resource_id
|
||||
# - resource_arn
|
||||
# - resource_tags
|
||||
# - status
|
||||
# - status_extended
|
||||
report.region = image.region
|
||||
report.resource_id = image.id
|
||||
report.resource_arn = image.arn
|
||||
# The resource_tags should be filled if the resource has the ability
|
||||
# of having tags, please check the service first.
|
||||
report.resource_tags = image.tags
|
||||
|
||||
# Then we need to create the business logic for the check
|
||||
# which always should be simple because the Prowler service
|
||||
# must do the heavy lifting and the check should be in charge
|
||||
# of parsing the data provided
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"EC2 AMI {image.id} is not public."
|
||||
|
||||
# In this example each "image" object has a boolean attribute
|
||||
# called "public" to set if the AMI is publicly shared
|
||||
if image.public:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"EC2 AMI {image.id} is currently public."
|
||||
)
|
||||
|
||||
# Then at the same level as the "report"
|
||||
# object we need to append it to the findings list.
|
||||
findings.append(report)
|
||||
|
||||
# Last thing to do is to return the findings list to Prowler
|
||||
return findings
|
||||
```
|
||||
|
||||
### Check Status
|
||||
|
||||
All the checks MUST fill the `report.status` and `report.status_extended` with the following criteria:
|
||||
|
||||
- Status -- `report.status`
|
||||
- `PASS` --> If the check is passing against the configured value.
|
||||
- `FAIL` --> If the check is passing against the configured value.
|
||||
- `INFO` --> This value cannot be used unless a manual operation is required in order to determine if the `report.status` is whether `PASS` or `FAIL`.
|
||||
- Status Extended -- `report.status_extended`
|
||||
- MUST end in a dot `.`
|
||||
- MUST include the service audited with the resource and a brief explanation of the result generated, e.g.: `EC2 AMI ami-0123456789 is not public.`
|
||||
|
||||
### Resource ID, Name and ARN
|
||||
All the hecks must fill the `report.resource_id` and `report.resource_arn` with the following criteria:
|
||||
|
||||
- AWS
|
||||
- Resource ID -- `report.resource_id`
|
||||
- AWS Account --> Account Number `123456789012`
|
||||
- AWS Resource --> Resource ID / Name
|
||||
- Root resource --> `<root_account>`
|
||||
- Resource ARN -- `report.resource_arn`
|
||||
- AWS Account --> Root ARN `arn:aws:iam::123456789012:root`
|
||||
- AWS Resource --> Resource ARN
|
||||
- Root resource --> Root ARN `arn:aws:iam::123456789012:root`
|
||||
- GCP
|
||||
- Resource ID -- `report.resource_id`
|
||||
- GCP Resource --> Resource ID
|
||||
- Resource Name -- `report.resource_name`
|
||||
- GCP Resource --> Resource Name
|
||||
- Azure
|
||||
- Resource ID -- `report.resource_id`
|
||||
- Azure Resource --> Resource ID
|
||||
- Resource Name -- `report.resource_name`
|
||||
- Azure Resource --> Resource Name
|
||||
|
||||
### Python Model
|
||||
The following is the Python model for the check's class.
|
||||
|
||||
As per August 5th 2023 the `Check_Metadata_Model` can be found [here](https://github.com/prowler-cloud/prowler/blob/master/prowler/lib/check/models.py#L59-L80).
|
||||
|
||||
```python
|
||||
class Check(ABC, Check_Metadata_Model):
|
||||
"""Prowler Check"""
|
||||
|
||||
def __init__(self, **data):
|
||||
"""Check's init function. Calls the CheckMetadataModel init."""
|
||||
# Parse the Check's metadata file
|
||||
metadata_file = (
|
||||
os.path.abspath(sys.modules[self.__module__].__file__)[:-3]
|
||||
+ ".metadata.json"
|
||||
)
|
||||
# Store it to validate them with Pydantic
|
||||
data = Check_Metadata_Model.parse_file(metadata_file).dict()
|
||||
# Calls parents init function
|
||||
super().__init__(**data)
|
||||
|
||||
def metadata(self) -> dict:
|
||||
"""Return the JSON representation of the check's metadata"""
|
||||
return self.json()
|
||||
|
||||
@abstractmethod
|
||||
def execute(self):
|
||||
"""Execute the check's logic"""
|
||||
```
|
||||
|
||||
### Using the audit config
|
||||
|
||||
Prowler has a [configuration file](../tutorials/configuration_file.md) which is used to pass certain configuration values to the checks, like the following:
|
||||
|
||||
```python title="ec2_securitygroup_with_many_ingress_egress_rules.py"
|
||||
class ec2_securitygroup_with_many_ingress_egress_rules(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
|
||||
# max_security_group_rules, default: 50
|
||||
max_security_group_rules = ec2_client.audit_config.get(
|
||||
"max_security_group_rules", 50
|
||||
)
|
||||
for security_group in ec2_client.security_groups:
|
||||
```
|
||||
|
||||
```yaml title="config.yaml"
|
||||
# AWS Configuration
|
||||
aws:
|
||||
# AWS EC2 Configuration
|
||||
|
||||
# aws.ec2_securitygroup_with_many_ingress_egress_rules
|
||||
# The default value is 50 rules
|
||||
max_security_group_rules: 50
|
||||
```
|
||||
|
||||
As you can see in the above code, within the service client, in this case the `ec2_client`, there is an object called `audit_config` which is a Python dictionary containing the values read from the configuration file.
|
||||
|
||||
In order to use it, you have to check first if the value is present in the configuration file. If the value is not present, you can create it in the `config.yaml` file and then, read it from the check.
|
||||
> It is mandatory to always use the `dictionary.get(value, default)` syntax to set a default value in the case the configuration value is not present.
|
||||
|
||||
|
||||
## Check Metadata
|
||||
|
||||
Each Prowler check has metadata associated which is stored at the same level of the check's folder in a file called A `check_name.metadata.json` containing the check's metadata.
|
||||
|
||||
> We are going to include comments in this example metadata JSON but they cannot be included because the JSON format does not allow comments.
|
||||
|
||||
```json
|
||||
{
|
||||
# Provider holds the Prowler provider which the checks belongs to
|
||||
"Provider": "aws",
|
||||
# CheckID holds check name
|
||||
"CheckID": "ec2_ami_public",
|
||||
# CheckTitle holds the title of the check
|
||||
"CheckTitle": "Ensure there are no EC2 AMIs set as Public.",
|
||||
# CheckType holds Software and Configuration Checks, check more here
|
||||
# https://docs.aws.amazon.com/securityhub/latest/userguide/asff-required-attributes.html#Types
|
||||
"CheckType": [
|
||||
"Infrastructure Security"
|
||||
],
|
||||
# ServiceName holds the provider service name
|
||||
"ServiceName": "ec2",
|
||||
# SubServiceName holds the service's subservice or resource used by the check
|
||||
"SubServiceName": "ami",
|
||||
# ResourceIdTemplate holds the unique ID for the resource used by the check
|
||||
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
|
||||
# Severity holds the check's severity, always in lowercase (critical, high, medium, low or informational)
|
||||
"Severity": "critical",
|
||||
# ResourceType only for AWS, holds the type from here
|
||||
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html
|
||||
"ResourceType": "Other",
|
||||
# Description holds the title of the check, for now is the same as CheckTitle
|
||||
"Description": "Ensure there are no EC2 AMIs set as Public.",
|
||||
# Risk holds the check risk if the result is FAIL
|
||||
"Risk": "When your AMIs are publicly accessible, they are available in the Community AMIs where everyone with an AWS account can use them to launch EC2 instances. Your AMIs could contain snapshots of your applications (including their data), therefore exposing your snapshots in this manner is not advised.",
|
||||
# RelatedUrl holds an URL with more information about the check purpose
|
||||
"RelatedUrl": "",
|
||||
# Remediation holds the information to help the practitioner to fix the issue in the case of the check raise a FAIL
|
||||
"Remediation": {
|
||||
# Code holds different methods to remediate the FAIL finding
|
||||
"Code": {
|
||||
# CLI holds the command in the provider native CLI to remediate it
|
||||
"CLI": "https://docs.bridgecrew.io/docs/public_8#cli-command",
|
||||
# NativeIaC holds the native IaC code to remediate it, use "https://docs.bridgecrew.io/docs"
|
||||
"NativeIaC": "",
|
||||
# Other holds the other commands, scripts or code to remediate it, use "https://www.trendmicro.com/cloudoneconformity"
|
||||
"Other": "https://docs.bridgecrew.io/docs/public_8#aws-console",
|
||||
# Terraform holds the Terraform code to remediate it, use "https://docs.bridgecrew.io/docs"
|
||||
"Terraform": ""
|
||||
},
|
||||
# Recommendation holds the recommendation for this check with a description and a related URL
|
||||
"Recommendation": {
|
||||
"Text": "We recommend your EC2 AMIs are not publicly accessible, or generally available in the Community AMIs.",
|
||||
"Url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/cancel-sharing-an-AMI.html"
|
||||
}
|
||||
},
|
||||
# Categories holds the category or categories where the check can be included, if applied
|
||||
"Categories": [
|
||||
"internet-exposed"
|
||||
],
|
||||
# DependsOn is not actively used for the moment but it will hold other
|
||||
# checks wich this check is dependant to
|
||||
"DependsOn": [],
|
||||
# RelatedTo is not actively used for the moment but it will hold other
|
||||
# checks wich this check is related to
|
||||
"RelatedTo": [],
|
||||
# Notes holds additional information not covered in this file
|
||||
"Notes": ""
|
||||
}
|
||||
```
|
||||
|
||||
### Remediation Code
|
||||
|
||||
For the Remediation Code we use the following knowledge base to fill it:
|
||||
|
||||
- Official documentation for the provider
|
||||
- https://docs.bridgecrew.io
|
||||
- https://www.trendmicro.com/cloudoneconformity
|
||||
- https://github.com/cloudmatos/matos/tree/master/remediations
|
||||
|
||||
### RelatedURL and Recommendation
|
||||
|
||||
The RelatedURL field must be filled with an URL from the provider's official documentation like https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharingamis-intro.html
|
||||
|
||||
Also, if not present you can use the Risk and Recommendation texts from the TrendMicro [CloudConformity](https://www.trendmicro.com/cloudoneconformity) guide.
|
||||
|
||||
|
||||
### Python Model
|
||||
The following is the Python model for the check's metadata model. We use the Pydantic's [BaseModel](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel) as the parent class.
|
||||
|
||||
As per August 5th 2023 the `Check_Metadata_Model` can be found [here](https://github.com/prowler-cloud/prowler/blob/master/prowler/lib/check/models.py#L34-L56).
|
||||
```python
|
||||
class Check_Metadata_Model(BaseModel):
|
||||
"""Check Metadata Model"""
|
||||
|
||||
Provider: str
|
||||
CheckID: str
|
||||
CheckTitle: str
|
||||
CheckType: list[str]
|
||||
ServiceName: str
|
||||
SubServiceName: str
|
||||
ResourceIdTemplate: str
|
||||
Severity: str
|
||||
ResourceType: str
|
||||
Description: str
|
||||
Risk: str
|
||||
RelatedUrl: str
|
||||
Remediation: Remediation
|
||||
Categories: list[str]
|
||||
DependsOn: list[str]
|
||||
RelatedTo: list[str]
|
||||
Notes: str
|
||||
# We set the compliance to None to
|
||||
# store the compliance later if supplied
|
||||
Compliance: list = None
|
||||
```
|
||||
8
docs/developer-guide/documentation.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## Contribute with documentation
|
||||
|
||||
We use `mkdocs` to build this Prowler documentation site so you can easily contribute back with new docs or improving them.
|
||||
|
||||
1. Install `mkdocs` with your favorite package manager.
|
||||
2. Inside the `prowler` repository folder run `mkdocs serve` and point your browser to `http://localhost:8000` and you will see live changes to your local copy of this documentation site.
|
||||
3. Make all needed changes to docs or add new documents. To do so just edit existing md files inside `prowler/docs` and if you are adding a new section or file please make sure you add it to `mkdocs.yaml` file in the root folder of the Prowler repo.
|
||||
4. Once you are done with changes, please send a pull request to us for review and merge. Thank you in advance!
|
||||
3
docs/developer-guide/integration-testing.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Integration Tests
|
||||
|
||||
Coming soon ...
|
||||
3
docs/developer-guide/integrations.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Create a new integration
|
||||
|
||||
Coming soon ...
|
||||
47
docs/developer-guide/introduction.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Developer Guide
|
||||
|
||||
You can extend Prowler in many different ways, in most cases you will want to create your own checks and compliance security frameworks, here is where you can learn about how to get started with it. We also include how to create custom outputs, integrations and more.
|
||||
|
||||
## Get the code and install all dependencies
|
||||
|
||||
First of all, you need a version of Python 3.9 or higher and also pip installed to be able to install all dependencies required. Once that is satisfied go a head and clone the repo:
|
||||
|
||||
```
|
||||
git clone https://github.com/prowler-cloud/prowler
|
||||
cd prowler
|
||||
```
|
||||
For isolation and avoid conflicts with other environments, we recommend usage of `poetry`:
|
||||
```
|
||||
pip install poetry
|
||||
```
|
||||
Then install all dependencies including the ones for developers:
|
||||
```
|
||||
poetry install
|
||||
poetry shell
|
||||
```
|
||||
|
||||
## Contributing with your code or fixes to Prowler
|
||||
|
||||
This repo has git pre-commit hooks managed via the [pre-commit](https://pre-commit.com/) tool. [Install](https://pre-commit.com/#install) it how ever you like, then in the root of this repo run:
|
||||
```shell
|
||||
pre-commit install
|
||||
```
|
||||
You should get an output like the following:
|
||||
```shell
|
||||
pre-commit installed at .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
Before we merge any of your pull requests we pass checks to the code, we use the following tools and automation to make sure the code is secure and dependencies up-to-dated (these should have been already installed if you ran `pipenv install -d`):
|
||||
|
||||
- [`bandit`](https://pypi.org/project/bandit/) for code security review.
|
||||
- [`safety`](https://pypi.org/project/safety/) and [`dependabot`](https://github.com/features/security) for dependencies.
|
||||
- [`hadolint`](https://github.com/hadolint/hadolint) and [`dockle`](https://github.com/goodwithtech/dockle) for our containers security.
|
||||
- [`Snyk`](https://docs.snyk.io/integrations/snyk-container-integrations/container-security-with-docker-hub-integration) in Docker Hub.
|
||||
- [`clair`](https://github.com/quay/clair) in Amazon ECR.
|
||||
- [`vulture`](https://pypi.org/project/vulture/), [`flake8`](https://pypi.org/project/flake8/), [`black`](https://pypi.org/project/black/) and [`pylint`](https://pypi.org/project/pylint/) for formatting and best practices.
|
||||
|
||||
You can see all dependencies in file `pyproject.toml`.
|
||||
|
||||
## Want some swag as appreciation for your contribution?
|
||||
|
||||
If you are like us and you love swag, we are happy to thank you for your contribution with some laptop stickers or whatever other swag we may have at that time. Please, tell us more details and your pull request link in our [Slack workspace here](https://join.slack.com/t/prowler-workspace/shared_invite/zt-1hix76xsl-2uq222JIXrC7Q8It~9ZNog). You can also reach out to Toni de la Fuente on Twitter [here](https://twitter.com/ToniBlyx), his DMs are open.
|
||||
3
docs/developer-guide/outputs.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Create a custom output format
|
||||
|
||||
Coming soon ...
|
||||
41
docs/developer-guide/security-compliance-framework.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Create a new security compliance framework
|
||||
|
||||
|
||||
## Introduction
|
||||
If you want to create or contribute with your own security frameworks or add public ones to Prowler you need to make sure the checks are available if not you have to create your own. Then create a compliance file per provider like in `prowler/compliance/<provider>/` and name it as `<framework>_<version>_<provider>.json` then follow the following format to create yours.
|
||||
|
||||
## Compliance Framework
|
||||
Each file version of a framework will have the following structure at high level with the case that each framework needs to be generally identified, one requirement can be also called one control but one requirement can be linked to multiple prowler checks.:
|
||||
|
||||
- `Framework`: string. Distinguish name of the framework, like CIS
|
||||
- `Provider`: string. Provider where the framework applies, such as AWS, Azure, OCI,...
|
||||
- `Version`: string. Version of the framework itself, like 1.4 for CIS.
|
||||
- `Requirements`: array of objects. Include all requirements or controls with the mapping to Prowler.
|
||||
- `Requirements_Id`: string. Unique identifier per each requirement in the specific framework
|
||||
- `Requirements_Description`: string. Description as in the framework.
|
||||
- `Requirements_Attributes`: array of objects. Includes all needed attributes per each requirement, like levels, sections, etc. Whatever helps to create a dedicated report with the result of the findings. Attributes would be taken as closely as possible from the framework's own terminology directly.
|
||||
- `Requirements_Checks`: array. Prowler checks that are needed to prove this requirement. It can be one or multiple checks. In case of no automation possible this can be empty.
|
||||
|
||||
```
|
||||
{
|
||||
"Framework": "<framework>-<provider>",
|
||||
"Version": "<version>",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "<unique-id>",
|
||||
"Description": "Requiemente full description",
|
||||
"Checks": [
|
||||
"Here is the prowler check or checks that is going to be executed"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
<Add here your custom attributes.>
|
||||
}
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Finally, to have a proper output file for your reports, your framework data model has to be created in `prowler/lib/outputs/models.py` and also the CLI table output in `prowler/lib/outputs/compliance.py`.
|
||||
235
docs/developer-guide/services.md
Normal file
@@ -0,0 +1,235 @@
|
||||
# Create a new Provider Service
|
||||
|
||||
Here you can find how to create a new service, or to complement an existing one, for a Prowler Provider.
|
||||
|
||||
## Introduction
|
||||
|
||||
To create a new service, you will need to create a folder inside the specific provider, i.e. `prowler/providers/<provider>/services/<service>/`.
|
||||
|
||||
Inside that folder, you MUST create the following files:
|
||||
|
||||
- An empty `__init__.py`: to make Python treat this service folder as a package.
|
||||
- A `<service>_service.py`, containing all the service's logic and API calls.
|
||||
- A `<service>_client_.py`, containing the initialization of the service's class we have just created so the checks's checks can use it.
|
||||
|
||||
## Service
|
||||
|
||||
The Prowler's service structure is the following and the way to initialise it is just by importing the service client in a check.
|
||||
|
||||
## Service Base Class
|
||||
|
||||
All the Prowler provider's services inherits from a base class depending on the provider used.
|
||||
|
||||
- [AWS Service Base Class](https://github.com/prowler-cloud/prowler/blob/22f8855ad7dad2e976dabff78611b643e234beaf/prowler/providers/aws/lib/service/service.py)
|
||||
- [GCP Service Base Class](https://github.com/prowler-cloud/prowler/blob/22f8855ad7dad2e976dabff78611b643e234beaf/prowler/providers/gcp/lib/service/service.py)
|
||||
- [Azure Service Base Class](https://github.com/prowler-cloud/prowler/blob/22f8855ad7dad2e976dabff78611b643e234beaf/prowler/providers/azure/lib/service/service.py)
|
||||
|
||||
Each class is used to initialize the credentials and the API's clients to be used in the service. If some threading is used it must be coded there.
|
||||
|
||||
## Service Class
|
||||
|
||||
Due to the complexity and differencies of each provider API we are going to use an example service to guide you in how can it be created.
|
||||
|
||||
The following is the `<service>_service.py` file:
|
||||
|
||||
```python title="Service Class"
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
# The following is just for the AWS provider
|
||||
from botocore.client import ClientError
|
||||
|
||||
# To use the Pydantic's BaseModel
|
||||
from pydantic import BaseModel
|
||||
|
||||
# Prowler logging library
|
||||
from prowler.lib.logger import logger
|
||||
|
||||
# Prowler resource filter, only for the AWS provider
|
||||
from prowler.lib.scan_filters.scan_filters import is_resource_filtered
|
||||
|
||||
# Provider parent class
|
||||
from prowler.providers.<provider>.lib.service.service import ServiceParentClass
|
||||
|
||||
|
||||
# Create a class for the Service
|
||||
################## <Service>
|
||||
class <Service>(ServiceParentClass):
|
||||
def __init__(self, audit_info):
|
||||
# Call Service Parent Class __init__
|
||||
# We use the __class__.__name__ to get it automatically
|
||||
# from the Service Class name but you can pass a custom
|
||||
# string if the provider's API service name is different
|
||||
super().__init__(__class__.__name__, audit_info)
|
||||
|
||||
# Create an empty dictionary of items to be gathered,
|
||||
# using the unique ID as the dictionary key
|
||||
# e.g., instances
|
||||
self.<items> = {}
|
||||
|
||||
# If you can parallelize by regions or locations
|
||||
# you can use the __threading_call__ function
|
||||
# available in the Service Parent Class
|
||||
self.__threading_call__(self.__describe_<items>__)
|
||||
|
||||
# Optionally you can create another function to retrieve
|
||||
# more data about each item without parallel
|
||||
self.__describe_<item>__()
|
||||
|
||||
def __describe_<items>__(self, regional_client):
|
||||
"""Get ALL <Service> <Items>"""
|
||||
logger.info("<Service> - Describing <Items>...")
|
||||
|
||||
# We MUST include a try/except block in each function
|
||||
try:
|
||||
|
||||
# Call to the provider API to retrieve the data we want
|
||||
describe_<items>_paginator = regional_client.get_paginator("describe_<items>")
|
||||
|
||||
# Paginator to get every item
|
||||
for page in describe_<items>_paginator.paginate():
|
||||
|
||||
# Another try/except within the loop for to continue looping
|
||||
# if something unexpected happens
|
||||
try:
|
||||
|
||||
for <item> in page["<Items>"]:
|
||||
|
||||
# For the AWS provider we MUST include the following lines to retrieve
|
||||
# or not data for the resource passed as argument using the --resource-arn
|
||||
if not self.audit_resources or (
|
||||
is_resource_filtered(<item>["<item_arn>"], self.audit_resources)
|
||||
):
|
||||
# Then we have to include the retrieved resource in the object
|
||||
# previously created
|
||||
self.<items>[<item_unique_id>] =
|
||||
<Item>(
|
||||
arn=stack["<item_arn>"],
|
||||
name=stack["<item_name>"],
|
||||
tags=stack.get("Tags", []),
|
||||
region=regional_client.region,
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{<provider_specific_field>} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
# In the except part we have to use the following code to log the errors
|
||||
except Exception as error:
|
||||
# Depending on each provider we can use the following fields in the logger:
|
||||
# - AWS: regional_client.region or self.region
|
||||
# - GCP: project_id and location
|
||||
# - Azure: subscription
|
||||
|
||||
logger.error(
|
||||
f"{<provider_specific_field>} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
|
||||
def __describe_<item>__(self):
|
||||
"""Get Details for a <Service> <Item>"""
|
||||
logger.info("<Service> - Describing <Item> to get specific details...")
|
||||
|
||||
# We MUST include a try/except block in each function
|
||||
try:
|
||||
|
||||
# Loop over the items retrieved in the previous function
|
||||
for <item> in self.<items>:
|
||||
|
||||
# When we perform calls to the Provider API within a for loop we have
|
||||
# to include another try/except block because in the cloud there are
|
||||
# ephemeral resources that can be deleted at the time we are checking them
|
||||
try:
|
||||
<item>_details = self.regional_clients[<item>.region].describe_<item>(
|
||||
<Attribute>=<item>.name
|
||||
)
|
||||
|
||||
# For example, check if item is Public. Here is important if we are
|
||||
# getting values from a dictionary we have to use the "dict.get()"
|
||||
# function with a default value in the case this value is not present
|
||||
<item>.public = <item>_details.get("Public", False)
|
||||
|
||||
|
||||
# In this except block, for example for the AWS Provider we can use
|
||||
# the botocore.ClientError exception and check for a specific error code
|
||||
# to raise a WARNING instead of an ERROR if some resource is not present.
|
||||
except ClientError as error:
|
||||
if error.response["Error"]["Code"] == "InvalidInstanceID.NotFound":
|
||||
logger.warning(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"{<provider_specific_field>} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
continue
|
||||
|
||||
# In the except part we have to use the following code to log the errors
|
||||
except Exception as error:
|
||||
# Depending on each provider we can use the following fields in the logger:
|
||||
# - AWS: regional_client.region or self.region
|
||||
# - GCP: project_id and location
|
||||
# - Azure: subscription
|
||||
|
||||
logger.error(
|
||||
f"{<item>.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
```
|
||||
|
||||
### Service Models
|
||||
|
||||
For each class object we need to model we use the Pydantic's [BaseModel](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel) to take advantage of the data validation.
|
||||
|
||||
```python title="Service Model"
|
||||
# In each service class we have to create some classes using
|
||||
# the Pydantic's Basemodel for the resources we want to audit.
|
||||
class <Item>(BaseModel):
|
||||
"""<Item> holds a <Service> <Item>"""
|
||||
|
||||
arn: str
|
||||
"""<Items>[].arn"""
|
||||
|
||||
name: str
|
||||
"""<Items>[].name"""
|
||||
|
||||
region: str
|
||||
"""<Items>[].region"""
|
||||
|
||||
public: bool
|
||||
"""<Items>[].public"""
|
||||
|
||||
# We can create Optional attributes set to None by default
|
||||
tags: Optional[list]
|
||||
"""<Items>[].tags"""
|
||||
```
|
||||
### Service Objects
|
||||
In the service each group of resources should be created as a Python [dictionary](https://docs.python.org/3/tutorial/datastructures.html#dictionaries). This is because we are performing lookups all the time and the Python dictionary lookup has [O(1) complexity](https://en.wikipedia.org/wiki/Big_O_notation#Orders_of_common_functions).
|
||||
|
||||
We MUST set as the dictionary key a unique ID, like the resource Unique ID or ARN.
|
||||
|
||||
Example:
|
||||
```python
|
||||
self.vpcs = {}
|
||||
self.vpcs["vpc-01234567890abcdef"] = VPC_Object_Class()
|
||||
```
|
||||
|
||||
## Service Client
|
||||
|
||||
Each Prowler service requires a service client to use the service in the checks.
|
||||
|
||||
The following is the `<service>_client.py` containing the initialization of the service's class we have just created so the service's checks can use them:
|
||||
|
||||
```python
|
||||
from prowler.providers.<provider>.lib.audit_info.audit_info import audit_info
|
||||
from prowler.providers.<provider>.services.<service>.<service>_service import <Service>
|
||||
|
||||
<service>_client = <Service>(audit_info)
|
||||
```
|
||||
|
||||
## Permissions
|
||||
|
||||
It is really important to check if the current Prowler's permissions for each provider are enough to implement a new service. If we need to include more please refer to the following documentaion and update it:
|
||||
|
||||
- AWS: https://docs.prowler.cloud/en/latest/getting-started/requirements/#aws-authentication
|
||||
- Azure: https://docs.prowler.cloud/en/latest/getting-started/requirements/#permissions
|
||||
- GCP: https://docs.prowler.cloud/en/latest/getting-started/requirements/#gcp-authentication
|
||||
590
docs/developer-guide/unit-testing.md
Normal file
@@ -0,0 +1,590 @@
|
||||
# Unit Tests
|
||||
|
||||
The unit tests for the Prowler checks varies between each provider supported.
|
||||
|
||||
Here we left some good reads about unit testing and things we've learnt through all the process.
|
||||
|
||||
**Python Testing**
|
||||
|
||||
- https://docs.python-guide.org/writing/tests/
|
||||
|
||||
**Where to patch**
|
||||
|
||||
- https://docs.python.org/3/library/unittest.mock.html#where-to-patch
|
||||
- https://stackoverflow.com/questions/893333/multiple-variables-in-a-with-statement
|
||||
- https://docs.python.org/3/reference/compound_stmts.html#the-with-statement
|
||||
|
||||
**Utils to trace mocking and test execution**
|
||||
|
||||
- https://news.ycombinator.com/item?id=36054868
|
||||
- https://docs.python.org/3/library/sys.html#sys.settrace
|
||||
- https://github.com/kunalb/panopticon
|
||||
|
||||
## General Recommendations
|
||||
|
||||
When creating tests for some provider's checks we follow these guidelines trying to cover as much test scenarios as possible:
|
||||
|
||||
1. Create a test without resource to generate 0 findings, because Prowler will generate 0 findings if a service does not contain the resources the check is looking for audit.
|
||||
2. Create test to generate both a `PASS` and a `FAIL` result.
|
||||
3. Create tests with more than 1 resource to evaluate how the check behaves and if the number of findings is right.
|
||||
|
||||
## How to run Prowler tests
|
||||
|
||||
To run the Prowler test suite you need to install the testing dependencies already included in the `pyproject.toml` file. If you didn't install it yet please read the developer guide introduction [here](./introduction.md#get-the-code-and-install-all-dependencies).
|
||||
|
||||
Then in the project's root path execute `pytest -n auto -vvv -s -x` or use the `Makefile` with `make test`.
|
||||
|
||||
Other commands to run tests:
|
||||
|
||||
- Run tests for a provider: `pytest -n auto -vvv -s -x tests/providers/<provider>/services`
|
||||
- Run tests for a provider service: `pytest -n auto -vvv -s -x tests/providers/<provider>/services/<service>`
|
||||
- Run tests for a provider check: `pytest -n auto -vvv -s -x tests/providers/<provider>/services/<service>/<check>`
|
||||
|
||||
> Refer to the [pytest documentation](https://docs.pytest.org/en/7.1.x/getting-started.html) documentation for more information.
|
||||
|
||||
## AWS
|
||||
|
||||
For the AWS provider we have ways to test a Prowler check based on the following criteria:
|
||||
|
||||
> Note: We use and contribute to the [Moto](https://github.com/getmoto/moto) library which allows us to easily mock out tests based on AWS infrastructure. **It's awesome!**
|
||||
|
||||
- AWS API calls covered by [Moto](https://github.com/getmoto/moto):
|
||||
- Service tests with `@mock_<service>`
|
||||
- Checks tests with `@mock_<service>`
|
||||
- AWS API calls not covered by Moto:
|
||||
- Service test with `mock_make_api_call`
|
||||
- Checks tests with [MagicMock](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.MagicMock)
|
||||
- AWS API calls partially covered by Moto:
|
||||
- Service test with `@mock_<service>` and `mock_make_api_call`
|
||||
- Checks tests with `@mock_<service>` and `mock_make_api_call`
|
||||
|
||||
In the following section we are going to explain all of the above scenarios with examples based on if the [Moto](https://github.com/getmoto/moto) library covers the AWS API calls made by the service. You can check the covered API calls [here](https://github.com/getmoto/moto/blob/master/IMPLEMENTATION_COVERAGE.md).
|
||||
|
||||
An important point for the AWS testing is that in each check we MUST have a unique `audit_info` which is the key object during the AWS execution to isolate the test execution.
|
||||
|
||||
Check the [Audit Info](./audit-info.md) section to get more details.
|
||||
|
||||
```python
|
||||
# We need to import the AWS_Audit_Info and the Audit_Metadata
|
||||
# to set the audit_info to call AWS APIs
|
||||
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info
|
||||
from prowler.providers.common.models import Audit_Metadata
|
||||
|
||||
AWS_ACCOUNT_NUMBER = "123456789012"
|
||||
|
||||
def set_mocked_audit_info(self):
|
||||
audit_info = AWS_Audit_Info(
|
||||
session_config=None,
|
||||
original_session=None,
|
||||
audit_session=session.Session(
|
||||
profile_name=None,
|
||||
botocore_session=None,
|
||||
),
|
||||
audit_config=None,
|
||||
audited_account=AWS_ACCOUNT_NUMBER,
|
||||
audited_account_arn=f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root",
|
||||
audited_user_id=None,
|
||||
audited_partition="aws",
|
||||
audited_identity_arn=None,
|
||||
profile=None,
|
||||
profile_region=None,
|
||||
credentials=None,
|
||||
assumed_role_info=None,
|
||||
audited_regions=["us-east-1", "eu-west-1"],
|
||||
organizations_metadata=None,
|
||||
audit_resources=None,
|
||||
mfa_enabled=False,
|
||||
audit_metadata=Audit_Metadata(
|
||||
services_scanned=0,
|
||||
expected_checks=[],
|
||||
completed_checks=0,
|
||||
audit_progress=0,
|
||||
),
|
||||
)
|
||||
|
||||
return audit_info
|
||||
```
|
||||
### Checks
|
||||
|
||||
For the AWS tests examples we are going to use the tests for the `iam_password_policy_uppercase` check.
|
||||
|
||||
This section is going to be divided based on the API coverage of the [Moto](https://github.com/getmoto/moto) library.
|
||||
|
||||
#### API calls covered
|
||||
|
||||
If the [Moto](https://github.com/getmoto/moto) library covers the API calls we want to test we can use the `@mock_<service>` decorator which will mocked out all the API calls made to AWS keeping the state within the code decorated, in this case the test function.
|
||||
|
||||
```python
|
||||
# We need to import the unittest.mock to allow us to patch some objects
|
||||
# not to use shared ones between test, hence to isolate the test
|
||||
from unittest import mock
|
||||
|
||||
# Boto3 client and session to call the AWS APIs
|
||||
from boto3 import client, session
|
||||
|
||||
# Moto decorator for the IAM service we want to mock
|
||||
from moto import mock_iam
|
||||
|
||||
# Constants used
|
||||
AWS_ACCOUNT_NUMBER = "123456789012"
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
# We always name the test classes like Test_<check_name>
|
||||
class Test_iam_password_policy_uppercase:
|
||||
|
||||
# We include the Moto decorator for the service we want to use
|
||||
# You can include more than one if two or more services are
|
||||
# involved in test
|
||||
@mock_iam
|
||||
# We name the tests with test_<service>_<check_name>_<test_action>
|
||||
def test_iam_password_policy_no_uppercase_flag(self):
|
||||
# First, we have to create an IAM client
|
||||
iam_client = client("iam", region_name=AWS_REGION)
|
||||
|
||||
# Then, since all the AWS accounts have a password
|
||||
# policy we want to set to False the RequireUppercaseCharacters
|
||||
iam_client.update_account_password_policy(RequireUppercaseCharacters=False)
|
||||
|
||||
# We set a mocked audit_info for AWS not to share the same audit state
|
||||
# between checks
|
||||
current_audit_info = self.set_mocked_audit_info()
|
||||
|
||||
# The Prowler service import MUST be made within the decorated
|
||||
# code not to make real API calls to the AWS service.
|
||||
from prowler.providers.aws.services.iam.iam_service import IAM
|
||||
|
||||
# Prowler for AWS uses a shared object called `current_audit_info` where it stores
|
||||
# the audit's state, credentials and configuration.
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.lib.audit_info.audit_info.current_audit_info",
|
||||
new=current_audit_info,
|
||||
),
|
||||
# We have to mock also the iam_client from the check to enforce that the iam_client used is the one
|
||||
# created within this check because patch != import, and if you execute tests in parallel some objects
|
||||
# can be already initialised hence the check won't be isolated
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.iam.iam_password_policy_uppercase.iam_password_policy_uppercase.iam_client",
|
||||
new=IAM(current_audit_info),
|
||||
):
|
||||
# We import the check within the two mocks not to initialise the iam_client with some shared information from
|
||||
# the current_audit_info or the IAM service.
|
||||
from prowler.providers.aws.services.iam.iam_password_policy_uppercase.iam_password_policy_uppercase import (
|
||||
iam_password_policy_uppercase,
|
||||
)
|
||||
|
||||
# Once imported, we only need to instantiate the check's class
|
||||
check = iam_password_policy_uppercase()
|
||||
|
||||
# And then, call the execute() function to run the check
|
||||
# against the IAM client we've set up.
|
||||
result = check.execute()
|
||||
|
||||
# Last but not least, we need to assert all the fields
|
||||
# from the check's results
|
||||
assert len(results) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].status_extended == "IAM password policy does not require at least one uppercase letter."
|
||||
assert result[0].resource_arn == f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root"
|
||||
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
|
||||
assert result[0].resource_tags == []
|
||||
assert result[0].region == AWS_REGION
|
||||
```
|
||||
|
||||
#### API calls not covered
|
||||
|
||||
If the IAM service for the check's we want to test is not covered by Moto we have to inject the objects in the service client using [MagicMock](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.MagicMock) because we cannot instantiate the service since it will make real calls to the AWS APIs.
|
||||
|
||||
> The following example uses the IAM GetAccountPasswordPolicy which is covered by Moto but this is only for demonstration purposes.
|
||||
|
||||
The following code shows how to use MagicMock to create the service objects.
|
||||
|
||||
```python
|
||||
# We need to import the unittest.mock to allow us to patch some objects
|
||||
# not to use shared ones between test, hence to isolate the test
|
||||
from unittest import mock
|
||||
|
||||
# Constants used
|
||||
AWS_ACCOUNT_NUMBER = "123456789012"
|
||||
AWS_REGION = "us-east-1"
|
||||
|
||||
|
||||
# We always name the test classes like Test_<check_name>
|
||||
class Test_iam_password_policy_uppercase:
|
||||
|
||||
# We name the tests with test_<service>_<check_name>_<test_action>
|
||||
def test_iam_password_policy_no_uppercase_flag(self):
|
||||
# Mocked client with MagicMock
|
||||
mocked_iam_client = mock.MagicMock
|
||||
|
||||
# Since the IAM Password Policy has their own model we have to import it
|
||||
from prowler.providers.aws.services.iam.iam_service import PasswordPolicy
|
||||
|
||||
# Create the mock PasswordPolicy object
|
||||
mocked_iam_client.password_policy = PasswordPolicy(
|
||||
length=5,
|
||||
symbols=True,
|
||||
numbers=True,
|
||||
# We set the value to False to test the check
|
||||
uppercase=False,
|
||||
lowercase=True,
|
||||
allow_change=False,
|
||||
expiration=True,
|
||||
)
|
||||
|
||||
# We set a mocked audit_info for AWS not to share the same audit state
|
||||
# between checks
|
||||
current_audit_info = self.set_mocked_audit_info()
|
||||
|
||||
# In this scenario we have to mock also the IAM service and the iam_client from the check to enforce that the iam_client used is the one created within this check because patch != import, and if you execute tests in parallel some objects can be already initialised hence the check won't be isolated.
|
||||
# In this case we don't use the Moto decorator, we use the mocked IAM client for both objects
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.iam.iam_service.IAM",
|
||||
new=mocked_iam_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.iam.iam_client.iam_client",
|
||||
new=mocked_iam_client,
|
||||
):
|
||||
# We import the check within the two mocks not to initialise the iam_client with some shared information from
|
||||
# the current_audit_info or the IAM service.
|
||||
from prowler.providers.aws.services.iam.iam_password_policy_uppercase.iam_password_policy_uppercase import (
|
||||
iam_password_policy_uppercase,
|
||||
)
|
||||
|
||||
# Once imported, we only need to instantiate the check's class
|
||||
check = iam_password_policy_uppercase()
|
||||
|
||||
# And then, call the execute() function to run the check
|
||||
# against the IAM client we've set up.
|
||||
result = check.execute()
|
||||
|
||||
# Last but not least, we need to assert all the fields
|
||||
# from the check's results
|
||||
assert len(results) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].status_extended == "IAM password policy does not require at least one uppercase letter."
|
||||
assert result[0].resource_arn == f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root"
|
||||
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
|
||||
assert result[0].resource_tags == []
|
||||
assert result[0].region == AWS_REGION
|
||||
```
|
||||
|
||||
#### API calls partially covered
|
||||
|
||||
If the API calls we want to use in the service are partially covered by the Moto decorator we have to create our own mocked API calls to use it in combination.
|
||||
|
||||
To do so, you need to mock the `botocore.client.BaseClient._make_api_call` function, which is the Boto3 function in charge of making the real API call to the AWS APIs, using `mock.patch <https://docs.python.org/3/library/unittest.mock.html#patch>`:
|
||||
|
||||
|
||||
```python
|
||||
|
||||
import boto3
|
||||
import botocore
|
||||
from unittest.mock import patch
|
||||
from moto import mock_iam
|
||||
|
||||
# Original botocore _make_api_call function
|
||||
orig = botocore.client.BaseClient._make_api_call
|
||||
|
||||
# Mocked botocore _make_api_call function
|
||||
def mock_make_api_call(self, operation_name, kwarg):
|
||||
# As you can see the operation_name has the get_account_password_policy snake_case form but
|
||||
# we are using the GetAccountPasswordPolicy form.
|
||||
# Rationale -> https://github.com/boto/botocore/blob/develop/botocore/client.py#L810:L816
|
||||
if operation_name == 'GetAccountPasswordPolicy':
|
||||
return {
|
||||
'PasswordPolicy': {
|
||||
'MinimumPasswordLength': 123,
|
||||
'RequireSymbols': True|False,
|
||||
'RequireNumbers': True|False,
|
||||
'RequireUppercaseCharacters': True|False,
|
||||
'RequireLowercaseCharacters': True|False,
|
||||
'AllowUsersToChangePassword': True|False,
|
||||
'ExpirePasswords': True|False,
|
||||
'MaxPasswordAge': 123,
|
||||
'PasswordReusePrevention': 123,
|
||||
'HardExpiry': True|False
|
||||
}
|
||||
}
|
||||
# If we don't want to patch the API call
|
||||
return orig(self, operation_name, kwarg)
|
||||
|
||||
# We always name the test classes like Test_<check_name>
|
||||
class Test_iam_password_policy_uppercase:
|
||||
|
||||
# We include the custom API call mock decorator for the service we want to use
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
# We include also the IAM Moto decorator for the API calls supported
|
||||
@mock_iam
|
||||
# We name the tests with test_<service>_<check_name>_<test_action>
|
||||
def test_iam_password_policy_no_uppercase_flag(self):
|
||||
# Check the previous section to see the check test since is the same
|
||||
```
|
||||
|
||||
Note that this does not use Moto, to keep it simple, but if you use any `moto`-decorators in addition to the patch, the call to `orig(self, operation_name, kwarg)` will be intercepted by Moto.
|
||||
|
||||
> The above code comes from here https://docs.getmoto.org/en/latest/docs/services/patching_other_services.html
|
||||
|
||||
#### Mocking more than one service
|
||||
|
||||
If the test your are creating belongs to a check that uses more than one provider service, you should mock each of the services used. For example, the check `cloudtrail_logs_s3_bucket_access_logging_enabled` requires the CloudTrail and the S3 client, hence the service's mock part of the test will be as follows:
|
||||
|
||||
|
||||
```python
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.lib.audit_info.audit_info.current_audit_info",
|
||||
new=mock_audit_info,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.cloudtrail.cloudtrail_logs_s3_bucket_access_logging_enabled.cloudtrail_logs_s3_bucket_access_logging_enabled.cloudtrail_client",
|
||||
new=Cloudtrail(mock_audit_info),
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.cloudtrail.cloudtrail_logs_s3_bucket_access_logging_enabled.cloudtrail_logs_s3_bucket_access_logging_enabled.s3_client",
|
||||
new=S3(mock_audit_info),
|
||||
):
|
||||
```
|
||||
|
||||
|
||||
As you can see in the above code, it is required to mock the AWS audit info and both services used.
|
||||
|
||||
|
||||
#### Patching vs. Importing
|
||||
|
||||
This is an important topic within the Prowler check's unit testing. Due to the dynamic nature of the check's load, the process of importing the service client from a check is the following:
|
||||
|
||||
1. `<check>.py`:
|
||||
```python
|
||||
from prowler.providers.<provider>.services.<service>.<service>_client import <service>_client
|
||||
```
|
||||
2. `<service>_client.py`:
|
||||
```python
|
||||
from prowler.providers.<provider>.lib.audit_info.audit_info import audit_info
|
||||
from prowler.providers.<provider>.services.<service>.<service>_service import <SERVICE>
|
||||
|
||||
<service>_client = <SERVICE>(audit_info)
|
||||
```
|
||||
|
||||
Due to the above import path it's not the same to patch the following objects because if you run a bunch of tests, either in parallel or not, some clients can be already instantiated by another check, hence your test exection will be using another test's service instance:
|
||||
|
||||
- `<service>_client` imported at `<check>.py`
|
||||
- `<service>_client` initialised at `<service>_client.py`
|
||||
- `<SERVICE>` imported at `<service>_client.py`
|
||||
|
||||
A useful read about this topic can be found in the following article: https://stackoverflow.com/questions/8658043/how-to-mock-an-import
|
||||
|
||||
|
||||
#### Different ways to mock the service client
|
||||
|
||||
##### Mocking the service client at the service client level
|
||||
|
||||
Mocking a service client using the following code ...
|
||||
|
||||
```python title="Mocking the service_client"
|
||||
with mock.patch(
|
||||
"prowler.providers.<provider>.lib.audit_info.audit_info.audit_info",
|
||||
new=audit_info,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.<service>.<check>.<check>.<service>_client",
|
||||
new=<SERVICE>(audit_info),
|
||||
):
|
||||
```
|
||||
will cause that the service will be initialised twice:
|
||||
|
||||
1. When the `<SERVICE>(audit_info)` is mocked out using `mock.patch` to have the object ready for the patching.
|
||||
2. At the `<service>_client.py` when we are patching it since the `mock.patch` needs to go to that object an initialise it, hence the `<SERVICE>(audit_info)` will be called again.
|
||||
|
||||
Then, when we import the `<service>_client.py` at `<check>.py`, since we are mocking where the object is used, Python will use the mocked one.
|
||||
|
||||
In the [next section](./unit-testing.md#mocking-the-service-and-the-service-client-at-the-service-client-level) you will see an improved version to mock objects.
|
||||
|
||||
|
||||
##### Mocking the service and the service client at the service client level
|
||||
Mocking a service client using the following code ...
|
||||
|
||||
```python title="Mocking the service and the service_client"
|
||||
with mock.patch(
|
||||
"prowler.providers.<provider>.lib.audit_info.audit_info.audit_info",
|
||||
new=audit_info,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.<service>.<SERVICE>",
|
||||
return_value=<SERVICE>(audit_info),
|
||||
) as service_client, mock.patch(
|
||||
"prowler.providers.aws.services.<service>.<service>_client.<service>_client",
|
||||
new=service_client,
|
||||
):
|
||||
```
|
||||
will cause that the service will be initialised once, just when the `<SERVICE>(audit_info)` is mocked out using `mock.patch`.
|
||||
|
||||
Then, at the check_level when Python tries to import the client with `from prowler.providers.<provider>.services.<service>.<service>_client`, since it is already mocked out, the execution will continue using the `service_client` without getting into the `<service>_client.py`.
|
||||
|
||||
|
||||
### Services
|
||||
|
||||
For testing the AWS services we have to follow the same logic as with the AWS checks, we have to check if the AWS API calls made by the service are covered by Moto and we have to test the service `__init__` to verifiy that the information is being correctly retrieved.
|
||||
|
||||
The service tests could act as *Integration Tests* since we test how the service retrieves the information from the provider, but since Moto or the custom mock objects mocks that calls this test will fall into *Unit Tests*.
|
||||
|
||||
Please refer to the [AWS checks tests](./unit-testing.md#checks) for more information on how to create tests and check the existing services tests [here](https://github.com/prowler-cloud/prowler/tree/master/tests/providers/aws/services).
|
||||
|
||||
## GCP
|
||||
|
||||
### Checks
|
||||
|
||||
For the GCP Provider we don't have any library to mock out the API calls we use. So in this scenario we inject the objects in the service client using [MagicMock](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.MagicMock).
|
||||
|
||||
The following code shows how to use MagicMock to create the service objects for a GCP check test.
|
||||
|
||||
```python
|
||||
# We need to import the unittest.mock to allow us to patch some objects
|
||||
# not to use shared ones between test, hence to isolate the test
|
||||
from unittest import mock
|
||||
|
||||
# GCP Constants
|
||||
GCP_PROJECT_ID = "123456789012"
|
||||
|
||||
# We are going to create a test for the compute_firewall_rdp_access_from_the_internet_allowed check
|
||||
class Test_compute_firewall_rdp_access_from_the_internet_allowed:
|
||||
|
||||
# We name the tests with test_<service>_<check_name>_<test_action>
|
||||
def test_compute_compute_firewall_rdp_access_from_the_internet_allowed_one_compliant_rule_with_valid_port(self):
|
||||
# Mocked client with MagicMock
|
||||
compute_client = mock.MagicMock
|
||||
|
||||
# Assign GCP client configuration
|
||||
compute_client.project_ids = [GCP_PROJECT_ID]
|
||||
compute_client.region = "global"
|
||||
|
||||
# Import the service resource model to create the mocked object
|
||||
from prowler.providers.gcp.services.compute.compute_service import Firewall
|
||||
|
||||
# Create the custom Firewall object to be tested
|
||||
firewall = Firewall(
|
||||
name="test",
|
||||
id="1234567890",
|
||||
source_ranges=["0.0.0.0/0"],
|
||||
direction="INGRESS",
|
||||
allowed_rules=[{"IPProtocol": "tcp", "ports": ["443"]}],
|
||||
project_id=GCP_PROJECT_ID,
|
||||
)
|
||||
compute_client.firewalls = [firewall]
|
||||
|
||||
# In this scenario we have to mock also the Compute service and the compute_client from the check to enforce that the compute_client used is the one created within this check because patch != import, and if you execute tests in parallel some objects can be already initialised hence the check won't be isolated.
|
||||
# In this case we don't use the Moto decorator, we use the mocked Compute client for both objects
|
||||
with mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_service.Compute",
|
||||
new=defender_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.gcp.services.compute.compute_client.compute_client",
|
||||
new=defender_client,
|
||||
):
|
||||
|
||||
# We import the check within the two mocks not to initialise the iam_client with some shared information from
|
||||
# the current_audit_info or the Compute service.
|
||||
from prowler.providers.gcp.services.compute.compute_firewall_rdp_access_from_the_internet_allowed.compute_firewall_rdp_access_from_the_internet_allowed import (
|
||||
compute_firewall_rdp_access_from_the_internet_allowed,
|
||||
)
|
||||
|
||||
# Once imported, we only need to instantiate the check's class
|
||||
check = compute_firewall_rdp_access_from_the_internet_allowed()
|
||||
|
||||
# And then, call the execute() function to run the check
|
||||
# against the IAM client we've set up.
|
||||
result = check.execute()
|
||||
|
||||
# Last but not least, we need to assert all the fields
|
||||
# from the check's results
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].status_extended == f"Firewall {firewall.name} does not expose port 3389 (RDP) to the internet."
|
||||
assert result[0].resource_name = firewall.name
|
||||
assert result[0].resource_id == firewall.id
|
||||
assert result[0].project_id = GCP_PROJECT_ID
|
||||
assert result[0].location = compute_client.region
|
||||
```
|
||||
|
||||
### Services
|
||||
|
||||
Coming soon ...
|
||||
|
||||
## Azure
|
||||
|
||||
### Checks
|
||||
|
||||
For the Azure Provider we don't have any library to mock out the API calls we use. So in this scenario we inject the objects in the service client using [MagicMock](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.MagicMock).
|
||||
|
||||
The following code shows how to use MagicMock to create the service objects for a Azure check test.
|
||||
|
||||
```python
|
||||
# We need to import the unittest.mock to allow us to patch some objects
|
||||
# not to use shared ones between test, hence to isolate the test
|
||||
from unittest import mock
|
||||
|
||||
from uuid import uuid4
|
||||
|
||||
# Azure Constants
|
||||
AZURE_SUSCRIPTION = str(uuid4())
|
||||
|
||||
|
||||
|
||||
# We are going to create a test for the Test_defender_ensure_defender_for_arm_is_on check
|
||||
class Test_defender_ensure_defender_for_arm_is_on:
|
||||
|
||||
# We name the tests with test_<service>_<check_name>_<test_action>
|
||||
def test_defender_defender_ensure_defender_for_arm_is_on_arm_pricing_tier_not_standard(self):
|
||||
resource_id = str(uuid4())
|
||||
|
||||
# Mocked client with MagicMock
|
||||
defender_client = mock.MagicMock
|
||||
|
||||
# Import the service resource model to create the mocked object
|
||||
from prowler.providers.azure.services.defender.defender_service import Defender_Pricing
|
||||
|
||||
# Create the custom Defender object to be tested
|
||||
defender_client.pricings = {
|
||||
AZURE_SUSCRIPTION: {
|
||||
"Arm": Defender_Pricing(
|
||||
resource_id=resource_id,
|
||||
pricing_tier="Not Standard",
|
||||
free_trial_remaining_time=0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
# In this scenario we have to mock also the Defender service and the defender_client from the check to enforce that the defender_client used is the one created within this check because patch != import, and if you execute tests in parallel some objects can be already initialised hence the check won't be isolated.
|
||||
# In this case we don't use the Moto decorator, we use the mocked Defender client for both objects
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.defender.defender_service.Defender",
|
||||
new=defender_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.azure.services.defender.defender_client.defender_client",
|
||||
new=defender_client,
|
||||
):
|
||||
|
||||
# We import the check within the two mocks not to initialise the iam_client with some shared information from
|
||||
# the current_audit_info or the Defender service.
|
||||
from prowler.providers.azure.services.defender.defender_ensure_defender_for_arm_is_on.defender_ensure_defender_for_arm_is_on import (
|
||||
defender_ensure_defender_for_arm_is_on,
|
||||
)
|
||||
|
||||
# Once imported, we only need to instantiate the check's class
|
||||
check = defender_ensure_defender_for_arm_is_on()
|
||||
|
||||
# And then, call the execute() function to run the check
|
||||
# against the IAM client we've set up.
|
||||
result = check.execute()
|
||||
|
||||
# Last but not least, we need to assert all the fields
|
||||
# from the check's results
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Defender plan Defender for ARM from subscription {AZURE_SUSCRIPTION} is set to OFF (pricing tier not standard)"
|
||||
)
|
||||
assert result[0].subscription == AZURE_SUSCRIPTION
|
||||
assert result[0].resource_name == "Defender plan ARM"
|
||||
assert result[0].resource_id == resource_id
|
||||
```
|
||||
|
||||
### Services
|
||||
|
||||
Coming soon ...
|
||||
@@ -1,6 +1,6 @@
|
||||
# Requirements
|
||||
|
||||
Prowler has been written in Python using the [AWS SDK (Boto3)](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html#) and [Azure SDK](https://learn.microsoft.com/en-us/python/api/overview/azure/?view=azure-python).
|
||||
Prowler has been written in Python using the [AWS SDK (Boto3)](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html#), [Azure SDK](https://azure.github.io/azure-sdk-for-python/) and [GCP API Python Client](https://github.com/googleapis/google-api-python-client/).
|
||||
## AWS
|
||||
|
||||
Since Prowler uses AWS Credentials under the hood, you can follow any authentication method as described [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-precedence).
|
||||
@@ -23,12 +23,19 @@ export AWS_SESSION_TOKEN="XXXXXXXXX"
|
||||
|
||||
Those credentials must be associated to a user or role with proper permissions to do all checks. To make sure, add the following AWS managed policies to the user or role being used:
|
||||
|
||||
- arn:aws:iam::aws:policy/SecurityAudit
|
||||
- arn:aws:iam::aws:policy/job-function/ViewOnlyAccess
|
||||
- `arn:aws:iam::aws:policy/SecurityAudit`
|
||||
- `arn:aws:iam::aws:policy/job-function/ViewOnlyAccess`
|
||||
|
||||
> Moreover, some read-only additional permissions are needed for several checks, make sure you attach also the custom policy [prowler-additions-policy.json](https://github.com/prowler-cloud/prowler/blob/master/iam/prowler-additions-policy.json) to the role you are using.
|
||||
> Moreover, some read-only additional permissions are needed for several checks, make sure you attach also the custom policy [prowler-additions-policy.json](https://github.com/prowler-cloud/prowler/blob/master/permissions/prowler-additions-policy.json) to the role you are using.
|
||||
|
||||
> If you want Prowler to send findings to [AWS Security Hub](https://aws.amazon.com/security-hub), make sure you also attach the custom policy [prowler-security-hub.json](https://github.com/prowler-cloud/prowler/blob/master/iam/prowler-security-hub.json).
|
||||
> If you want Prowler to send findings to [AWS Security Hub](https://aws.amazon.com/security-hub), make sure you also attach the custom policy [prowler-security-hub.json](https://github.com/prowler-cloud/prowler/blob/master/permissions/prowler-security-hub.json).
|
||||
|
||||
### Multi-Factor Authentication
|
||||
|
||||
If your IAM entity enforces MFA you can use `--mfa` and Prowler will ask you to input the following values to get a new session:
|
||||
|
||||
- ARN of your MFA device
|
||||
- TOTP (Time-Based One-Time Password)
|
||||
|
||||
## Azure
|
||||
|
||||
@@ -52,7 +59,7 @@ export AZURE_CLIENT_SECRET="XXXXXXX"
|
||||
If you try to execute Prowler with the `--sp-env-auth` flag and those variables are empty or not exported, the execution is going to fail.
|
||||
### AZ CLI / Browser / Managed Identity authentication
|
||||
|
||||
The other three cases does not need additional configuration, `--az-cli-auth` and `--managed-identity-auth` are automated options, `--browser-auth` needs the user to authenticate using the default browser to start the scan.
|
||||
The other three cases does not need additional configuration, `--az-cli-auth` and `--managed-identity-auth` are automated options. To use `--browser-auth` the user needs to authenticate against Azure using the default browser to start the scan, also `tenant-id` is required.
|
||||
|
||||
### Permissions
|
||||
|
||||
@@ -79,3 +86,21 @@ Regarding the subscription scope, Prowler by default scans all the subscriptions
|
||||
|
||||
- `Security Reader`
|
||||
- `Reader`
|
||||
|
||||
## Google Cloud
|
||||
|
||||
### GCP Authentication
|
||||
|
||||
Prowler will follow the same credentials search as [Google authentication libraries](https://cloud.google.com/docs/authentication/application-default-credentials#search_order):
|
||||
|
||||
1. [GOOGLE_APPLICATION_CREDENTIALS environment variable](https://cloud.google.com/docs/authentication/application-default-credentials#GAC)
|
||||
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
||||
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
||||
|
||||
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the following roles to the member associated with the credentials:
|
||||
|
||||
- Viewer
|
||||
- Security Reviewer
|
||||
- Stackdriver Account Viewer
|
||||
|
||||
> By default, `prowler` will scan all accessible GCP Projects, use flag `--project-ids` to specify the projects to be scanned.
|
||||
|
||||
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 258 KiB After Width: | Height: | Size: 283 KiB |
BIN
docs/img/output-html.png
Normal file
|
After Width: | Height: | Size: 631 KiB |
1
docs/img/prowler-icon.svg
Normal file
|
After Width: | Height: | Size: 11 KiB |
1
docs/img/prowler-logo.svg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/img/quick-inventory.jpg
Normal file
|
After Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 220 KiB |
105
docs/index.md
@@ -5,18 +5,18 @@
|
||||
|
||||
# Prowler Documentation
|
||||
|
||||
**Welcome to [Prowler Open Source v3](https://github.com/prowler-cloud/prowler/) Documentation!** 📄
|
||||
**Welcome to [Prowler Open Source v3](https://github.com/prowler-cloud/prowler/) Documentation!** 📄
|
||||
|
||||
For **Prowler v2 Documentation**, please go [here](https://github.com/prowler-cloud/prowler/tree/2.12.0) to the branch and its README.md.
|
||||
|
||||
- You are currently in the **Getting Started** section where you can find general information and requirements to help you start with the tool.
|
||||
- In the [Tutorials](tutorials/overview) section you will see how to take advantage of all the features in Prowler.
|
||||
- In the [Contact Us](contact) section you can find how to reach us out in case of technical issues.
|
||||
- In the [About](about) section you will find more information about the Prowler team and license.
|
||||
- In the [Tutorials](./tutorials/misc.md) section you will see how to take advantage of all the features in Prowler.
|
||||
- In the [Contact Us](./contact.md) section you can find how to reach us out in case of technical issues.
|
||||
- In the [About](./about.md) section you will find more information about the Prowler team and license.
|
||||
|
||||
## About Prowler
|
||||
|
||||
**Prowler** is an Open Source security tool to perform AWS and Azure security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness.
|
||||
**Prowler** is an Open Source security tool to perform AWS, Azure and Google Cloud security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness.
|
||||
|
||||
It contains hundreds of controls covering CIS, PCI-DSS, ISO27001, GDPR, HIPAA, FFIEC, SOC2, AWS FTR, ENS and custom security frameworks.
|
||||
|
||||
@@ -40,12 +40,12 @@ Prowler is available as a project in [PyPI](https://pypi.org/project/prowler-clo
|
||||
|
||||
* `Python >= 3.9`
|
||||
* `Python pip >= 3.9`
|
||||
* AWS and/or Azure credentials
|
||||
* AWS, GCP and/or Azure credentials
|
||||
|
||||
_Commands_:
|
||||
|
||||
``` bash
|
||||
pip install prowler-cloud
|
||||
pip install prowler
|
||||
prowler -v
|
||||
```
|
||||
|
||||
@@ -54,7 +54,7 @@ Prowler is available as a project in [PyPI](https://pypi.org/project/prowler-clo
|
||||
_Requirements_:
|
||||
|
||||
* Have `docker` installed: https://docs.docker.com/get-docker/.
|
||||
* AWS and/or Azure credentials
|
||||
* AWS, GCP and/or Azure credentials
|
||||
* In the command below, change `-v` to your local directory path in order to access the reports.
|
||||
|
||||
_Commands_:
|
||||
@@ -71,7 +71,7 @@ Prowler is available as a project in [PyPI](https://pypi.org/project/prowler-clo
|
||||
|
||||
_Requirements for Ubuntu 20.04.3 LTS_:
|
||||
|
||||
* AWS and/or Azure credentials
|
||||
* AWS, GCP and/or Azure credentials
|
||||
* Install python 3.9 with: `sudo apt-get install python3.9`
|
||||
* Remove python 3.8 to avoid conflicts if you can: `sudo apt-get remove python3.8`
|
||||
* Make sure you have the python3 distutils package installed: `sudo apt-get install python3-distutils`
|
||||
@@ -82,27 +82,58 @@ Prowler is available as a project in [PyPI](https://pypi.org/project/prowler-clo
|
||||
_Commands_:
|
||||
|
||||
```
|
||||
pip3.9 install prowler-cloud
|
||||
pip3.9 install prowler
|
||||
export PATH=$PATH:/home/$HOME/.local/bin/
|
||||
prowler -v
|
||||
```
|
||||
|
||||
=== "GitHub"
|
||||
|
||||
_Requirements for Developers_:
|
||||
|
||||
* AWS, GCP and/or Azure credentials
|
||||
* `git`, `Python >= 3.9`, `pip` and `poetry` installed (`pip install poetry`)
|
||||
|
||||
_Commands_:
|
||||
|
||||
```
|
||||
git clone https://github.com/prowler-cloud/prowler
|
||||
cd prowler
|
||||
poetry shell
|
||||
poetry install
|
||||
python prowler.py -v
|
||||
```
|
||||
|
||||
=== "Amazon Linux 2"
|
||||
|
||||
_Requirements_:
|
||||
|
||||
* AWS and/or Azure credentials
|
||||
* Latest Amazon Linux 2 should come with Python 3.9 already installed however it may need pip. Install Python pip 3.9 with: `sudo dnf install -y python3-pip`.
|
||||
* AWS, GCP and/or Azure credentials
|
||||
* Latest Amazon Linux 2 should come with Python 3.9 already installed however it may need pip. Install Python pip 3.9 with: `sudo yum install -y python3-pip`.
|
||||
* Make sure setuptools for python is already installed with: `pip3 install setuptools`
|
||||
|
||||
_Commands_:
|
||||
|
||||
```
|
||||
pip3.9 install prowler-cloud
|
||||
pip3.9 install prowler
|
||||
export PATH=$PATH:/home/$HOME/.local/bin/
|
||||
prowler -v
|
||||
```
|
||||
|
||||
=== "Brew"
|
||||
|
||||
_Requirements_:
|
||||
|
||||
* `Brew` installed in your Mac or Linux
|
||||
* AWS, GCP and/or Azure credentials
|
||||
|
||||
_Commands_:
|
||||
|
||||
``` bash
|
||||
brew install prowler
|
||||
prowler -v
|
||||
```
|
||||
|
||||
=== "AWS CloudShell"
|
||||
|
||||
Prowler can be easely executed in AWS CloudShell but it has some prerequsites to be able to to so. AWS CloudShell is a container running with `Amazon Linux release 2 (Karoo)` that comes with Python 3.7, since Prowler requires Python >= 3.9 we need to first install a newer version of Python. Follow the steps below to successfully execute Prowler v3 in AWS CloudShell:
|
||||
@@ -118,13 +149,13 @@ Prowler is available as a project in [PyPI](https://pypi.org/project/prowler-clo
|
||||
./configure --enable-optimizations
|
||||
sudo make altinstall
|
||||
python3.9 --version
|
||||
cd
|
||||
cd
|
||||
```
|
||||
_Commands_:
|
||||
|
||||
* Once Python 3.9 is available we can install Prowler from pip:
|
||||
```
|
||||
pip3.9 install prowler-cloud
|
||||
pip3.9 install prowler
|
||||
prowler -v
|
||||
```
|
||||
|
||||
@@ -139,7 +170,7 @@ Prowler is available as a project in [PyPI](https://pypi.org/project/prowler-clo
|
||||
_Commands_:
|
||||
|
||||
```
|
||||
pip install prowler-cloud
|
||||
pip install prowler
|
||||
prowler -v
|
||||
```
|
||||
|
||||
@@ -154,7 +185,7 @@ The available versions of Prowler are the following:
|
||||
The container images are available here:
|
||||
|
||||
- [DockerHub](https://hub.docker.com/r/toniblyx/prowler/tags)
|
||||
- [AWS Public ECR](https://gallery.ecr.aws/o4g1s5r6/prowler)
|
||||
- [AWS Public ECR](https://gallery.ecr.aws/prowler-cloud/prowler)
|
||||
|
||||
## High level architecture
|
||||
|
||||
@@ -163,16 +194,16 @@ You can run Prowler from your workstation, an EC2 instance, Fargate or any other
|
||||

|
||||
## Basic Usage
|
||||
|
||||
To run Prowler, you will need to specify the provider (e.g aws or azure):
|
||||
To run Prowler, you will need to specify the provider (e.g aws, gcp or azure):
|
||||
> If no provider specified, AWS will be used for backward compatibility with most of v2 options.
|
||||
|
||||
```console
|
||||
prowler <provider>
|
||||
```
|
||||

|
||||
> Running the `prowler` command without options will use your environment variable credentials, see [Requirements](getting-started/requirements/) section to review the credentials settings.
|
||||
> Running the `prowler` command without options will use your environment variable credentials, see [Requirements](./getting-started/requirements.md) section to review the credentials settings.
|
||||
|
||||
If you miss the former output you can use `--verbose` but Prowler v3 is smoking fast so you won't see much ;)
|
||||
If you miss the former output you can use `--verbose` but Prowler v3 is smoking fast, so you won't see much ;)
|
||||
|
||||
By default, Prowler will generate a CSV, JSON and HTML reports, however you can generate a JSON-ASFF (used by AWS Security Hub) report with `-M` or `--output-modes`:
|
||||
|
||||
@@ -195,6 +226,7 @@ For executing specific checks or services you can use options `-c`/`checks` or `
|
||||
```console
|
||||
prowler azure --checks storage_blob_public_access_level_is_disabled
|
||||
prowler aws --services s3 ec2
|
||||
prowler gcp --services iam compute
|
||||
```
|
||||
|
||||
Also, checks and services can be excluded with options `-e`/`--excluded-checks` or `--excluded-services`:
|
||||
@@ -202,9 +234,10 @@ Also, checks and services can be excluded with options `-e`/`--excluded-checks`
|
||||
```console
|
||||
prowler aws --excluded-checks s3_bucket_public_access
|
||||
prowler azure --excluded-services defender iam
|
||||
prowler gcp --excluded-services kms
|
||||
```
|
||||
|
||||
More options and executions methods that will save your time in [Miscelaneous](tutorials/misc.md).
|
||||
More options and executions methods that will save your time in [Miscellaneous](tutorials/misc.md).
|
||||
|
||||
You can always use `-h`/`--help` to access to the usage information and all the possible options:
|
||||
|
||||
@@ -221,6 +254,8 @@ prowler aws --profile custom-profile -f us-east-1 eu-south-2
|
||||
```
|
||||
> By default, `prowler` will scan all AWS regions.
|
||||
|
||||
See more details about AWS Authentication in [Requirements](getting-started/requirements.md)
|
||||
|
||||
### Azure
|
||||
|
||||
With Azure you need to specify which auth method is going to be used:
|
||||
@@ -233,15 +268,37 @@ prowler azure --sp-env-auth
|
||||
prowler azure --az-cli-auth
|
||||
|
||||
# To use browser authentication
|
||||
prowler azure --browser-auth
|
||||
prowler azure --browser-auth --tenant-id "XXXXXXXX"
|
||||
|
||||
# To use managed identity auth
|
||||
prowler azure --managed-identity-auth
|
||||
```
|
||||
|
||||
More details in [Requirements](getting-started/requirements.md)
|
||||
See more details about Azure Authentication in [Requirements](getting-started/requirements.md)
|
||||
|
||||
Prowler by default scans all the subscriptions that is allowed to scan, if you want to scan a single subscription or various concrete subscriptions you can use the following flag (using az cli auth as example):
|
||||
Prowler by default scans all the subscriptions that is allowed to scan, if you want to scan a single subscription or various specific subscriptions you can use the following flag (using az cli auth as example):
|
||||
```console
|
||||
prowler azure --az-cli-auth --subscription-ids <subscription ID 1> <subscription ID 2> ... <subscription ID N>
|
||||
```
|
||||
|
||||
### Google Cloud
|
||||
|
||||
Prowler will use by default your User Account credentials, you can configure it using:
|
||||
|
||||
- `gcloud init` to use a new account
|
||||
- `gcloud config set account <account>` to use an existing account
|
||||
|
||||
Then, obtain your access credentials using: `gcloud auth application-default login`
|
||||
|
||||
Otherwise, you can generate and download Service Account keys in JSON format (refer to https://cloud.google.com/iam/docs/creating-managing-service-account-keys) and provide the location of the file with the following argument:
|
||||
|
||||
```console
|
||||
prowler gcp --credentials-file path
|
||||
```
|
||||
|
||||
Prowler by default scans all the GCP Projects that is allowed to scan, if you want to scan a single project or various specific projects you can use the following flag:
|
||||
```console
|
||||
prowler gcp --project-ids <Project ID 1> <Project ID 2> ... <Project ID N>
|
||||
```
|
||||
|
||||
See more details about GCP Authentication in [Requirements](getting-started/requirements.md)
|
||||
|
||||
24
docs/security.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Security
|
||||
|
||||
## Software Security
|
||||
|
||||
As an **AWS Partner** and we have passed the [AWS Foundation Technical Review (FTR)](https://aws.amazon.com/partners/foundational-technical-review/) and we use the following tools and automation to make sure our code is secure and dependencies up-to-dated:
|
||||
|
||||
- `bandit` for code security review.
|
||||
- `safety` and `dependabot` for dependencies.
|
||||
- `hadolint` and `dockle` for our containers security.
|
||||
- `snyk` in Docker Hub.
|
||||
- `clair` in Amazon ECR.
|
||||
- `vulture`, `flake8`, `black` and `pylint` for formatting and best practices.
|
||||
|
||||
## Reporting Vulnerabilities
|
||||
|
||||
If you would like to report a vulnerability or have a security concern regarding Prowler Open Source or ProwlerPro service, please submit the information by contacting to help@prowler.pro.
|
||||
|
||||
The information you share with Verica as part of this process is kept confidential within Verica and the Prowler team. We will only share this information with a third party if the vulnerability you report is found to affect a third-party product, in which case we will share this information with the third-party product's author or manufacturer. Otherwise, we will only share this information as permitted by you.
|
||||
|
||||
We will review the submitted report, and assign it a tracking number. We will then respond to you, acknowledging receipt of the report, and outline the next steps in the process.
|
||||
|
||||
You will receive a non-automated response to your initial contact within 24 hours, confirming receipt of your reported vulnerability.
|
||||
|
||||
We will coordinate public notification of any validated vulnerability with you. Where possible, we prefer that our respective public disclosures be posted simultaneously.
|
||||
@@ -1,8 +1,14 @@
|
||||
# Troubleshooting
|
||||
|
||||
- Running `prowler` I get `[File: utils.py:15] [Module: utils] CRITICAL: path/redacted: OSError[13]`:
|
||||
- **Running `prowler` I get `[File: utils.py:15] [Module: utils] CRITICAL: path/redacted: OSError[13]`**:
|
||||
|
||||
That is an error related to file descriptors or opened files allowed by your operating system, with `ulimit -n 1000` you solve the issue. We have seen this issue in some macOS Ventura.
|
||||
That is an error related to file descriptors or opened files allowed by your operating system.
|
||||
|
||||
In macOS Ventura, the default value for the `file descriptors` is `256`. With the following command `ulimit -n 1000` you'll increase that value and solve the issue.
|
||||
|
||||
If you have a different OS and you are experiencing the same, please increase the value of your `file descriptors`. You can check it running `ulimit -a | grep "file descriptors"`.
|
||||
|
||||
This error is also related with a lack of system requirements. To improve performance, Prowler stores information in memory so it may need to be run in a system with more than 1GB of memory.
|
||||
|
||||
|
||||
See section [Logging](/tutorials/logging/) for further information or [conctact us](/contact/).
|
||||
See section [Logging](./tutorials/logging.md) for further information or [contact us](./contact.md).
|
||||
|
||||
@@ -7,35 +7,80 @@ You can use `-w`/`--allowlist-file` with the path of your allowlist yaml file, b
|
||||
|
||||
## Allowlist Yaml File Syntax
|
||||
|
||||
### Account, Check and/or Region can be * to apply for all the cases
|
||||
### Resources is a list that can have either Regex or Keywords:
|
||||
### Account, Check and/or Region can be * to apply for all the cases.
|
||||
### Resources and tags are lists that can have either Regex or Keywords.
|
||||
### Tags is an optional list that matches on tuples of 'key=value' and are "ANDed" together.
|
||||
### Use an alternation Regex to match one of multiple tags with "ORed" logic.
|
||||
### For each check you can except Accounts, Regions, Resources and/or Tags.
|
||||
########################### ALLOWLIST EXAMPLE ###########################
|
||||
Allowlist:
|
||||
Accounts:
|
||||
Accounts:
|
||||
"123456789012":
|
||||
Checks:
|
||||
Checks:
|
||||
"iam_user_hardware_mfa_enabled":
|
||||
Regions:
|
||||
Regions:
|
||||
- "us-east-1"
|
||||
Resources:
|
||||
Resources:
|
||||
- "user-1" # Will ignore user-1 in check iam_user_hardware_mfa_enabled
|
||||
- "user-2" # Will ignore user-2 in check iam_user_hardware_mfa_enabled
|
||||
"*":
|
||||
Regions:
|
||||
"ec2_*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "test" # Will ignore every resource containing the string "test" in every account and region
|
||||
Resources:
|
||||
- "*" # Will ignore every EC2 check in every account and region
|
||||
"*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "test"
|
||||
Tags:
|
||||
- "test=test" # Will ignore every resource containing the string "test" and the tags 'test=test' and
|
||||
- "project=test|project=stage" # either of ('project=test' OR project=stage) in account 123456789012 and every region
|
||||
|
||||
"*":
|
||||
Checks:
|
||||
Checks:
|
||||
"s3_bucket_object_versioning":
|
||||
Regions:
|
||||
Regions:
|
||||
- "eu-west-1"
|
||||
- "us-east-1"
|
||||
Resources:
|
||||
Resources:
|
||||
- "ci-logs" # Will ignore bucket "ci-logs" AND ALSO bucket "ci-logs-replica" in specified check and regions
|
||||
- "logs" # Will ignore EVERY BUCKET containing the string "logs" in specified check and regions
|
||||
- "[[:alnum:]]+-logs" # Will ignore all buckets containing the terms ci-logs, qa-logs, etc. in specified check and regions
|
||||
- ".+-logs" # Will ignore all buckets containing the terms ci-logs, qa-logs, etc. in specified check and regions
|
||||
"*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "*"
|
||||
Tags:
|
||||
- "environment=dev" # Will ignore every resource containing the tag 'environment=dev' in every account and region
|
||||
|
||||
"*":
|
||||
Checks:
|
||||
"ecs_task_definitions_no_environment_secrets":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "*"
|
||||
Exceptions:
|
||||
Accounts:
|
||||
- "0123456789012"
|
||||
Regions:
|
||||
- "eu-west-1"
|
||||
- "eu-south-2" # Will ignore every resource in check ecs_task_definitions_no_environment_secrets except the ones in account 0123456789012 located in eu-south-2 or eu-west-1
|
||||
|
||||
"123456789012":
|
||||
Checks:
|
||||
"*":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "*"
|
||||
Exceptions:
|
||||
Resources:
|
||||
- "test"
|
||||
Tags:
|
||||
- "environment=prod" # Will ignore every resource except in account 123456789012 except the ones containing the string "test" and tag environment=prod
|
||||
|
||||
|
||||
## Supported Allowlist Locations
|
||||
@@ -63,14 +108,50 @@ prowler aws -w arn:aws:dynamodb:<region_name>:<account_id>:table/<table_name>
|
||||
```
|
||||
|
||||
1. The DynamoDB Table must have the following String keys:
|
||||
<img src="/img/allowlist-keys.png"/>
|
||||
<img src="../img/allowlist-keys.png"/>
|
||||
|
||||
- The Allowlist Table must have the following columns:
|
||||
- Accounts (String): This field can contain either an Account ID or an `*` (which applies to all the accounts that use this table as an allowlist).
|
||||
- Checks (String): This field can contain either a Prowler Check Name or an `*` (which applies to all the scanned checks).
|
||||
- Regions (List): This field contains a list of regions where this allowlist rule is applied (it can also contains an `*` to apply all scanned regions).
|
||||
- Resources (List): This field contains a list of regex expressions that applies to the resources that are wanted to be allowlisted.
|
||||
- Tags (List): -Optional- This field contains a list of tuples in the form of 'key=value' that applies to the resources tags that are wanted to be allowlisted.
|
||||
- Exceptions (Map): -Optional- This field contains a map of lists of accounts/regions/resources/tags that are wanted to be excepted in the allowlist.
|
||||
|
||||
<img src="/img/allowlist-row.png"/>
|
||||
The following example will allowlist all resources in all accounts for the EC2 checks in the regions `eu-west-1` and `us-east-1` with the tags `environment=dev` and `environment=prod`, except the resources containing the string `test` in the account `012345678912` and region `eu-west-1` with the tag `environment=prod`:
|
||||
|
||||
<img src="../img/allowlist-row.png"/>
|
||||
|
||||
> Make sure that the used AWS credentials have `dynamodb:PartiQLSelect` permissions in the table.
|
||||
|
||||
### AWS Lambda ARN
|
||||
|
||||
You will need to pass the AWS Lambda Function ARN:
|
||||
|
||||
```
|
||||
prowler aws -w arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME
|
||||
```
|
||||
|
||||
Make sure that the credentials that Prowler uses can invoke the Lambda Function:
|
||||
|
||||
```
|
||||
- PolicyName: GetAllowList
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Action: 'lambda:InvokeFunction'
|
||||
Effect: Allow
|
||||
Resource: arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME
|
||||
```
|
||||
|
||||
The Lambda Function can then generate an Allowlist dynamically. Here is the code an example Python Lambda Function that
|
||||
generates an Allowlist:
|
||||
|
||||
```
|
||||
def handler(event, context):
|
||||
checks = {}
|
||||
checks["vpc_flow_logs_enabled"] = { "Regions": [ "*" ], "Resources": [ "" ], Optional("Tags"): [ "key:value" ] }
|
||||
|
||||
al = { "Allowlist": { "Accounts": { "*": { "Checks": checks } } } }
|
||||
return al
|
||||
```
|
||||
|
||||
35
docs/tutorials/aws/authentication.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# AWS Authentication
|
||||
|
||||
Make sure you have properly configured your AWS-CLI with a valid Access Key and Region or declare AWS variables properly (or instance profile/role):
|
||||
|
||||
```console
|
||||
aws configure
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```console
|
||||
export AWS_ACCESS_KEY_ID="ASXXXXXXX"
|
||||
export AWS_SECRET_ACCESS_KEY="XXXXXXXXX"
|
||||
export AWS_SESSION_TOKEN="XXXXXXXXX"
|
||||
```
|
||||
|
||||
Those credentials must be associated to a user or role with proper permissions to do all checks. To make sure, add the following AWS managed policies to the user or role being used:
|
||||
|
||||
- `arn:aws:iam::aws:policy/SecurityAudit`
|
||||
- `arn:aws:iam::aws:policy/job-function/ViewOnlyAccess`
|
||||
|
||||
> Moreover, some read-only additional permissions are needed for several checks, make sure you attach also the custom policy [prowler-additions-policy.json](https://github.com/prowler-cloud/prowler/blob/master/permissions/prowler-additions-policy.json) to the role you are using.
|
||||
|
||||
> If you want Prowler to send findings to [AWS Security Hub](https://aws.amazon.com/security-hub), make sure you also attach the custom policy [prowler-security-hub.json](https://github.com/prowler-cloud/prowler/blob/master/permissions/prowler-security-hub.json).
|
||||
|
||||
## Multi-Factor Authentication
|
||||
|
||||
If your IAM entity enforces MFA you can use `--mfa` and Prowler will ask you to input the following values to get a new session:
|
||||
|
||||
- ARN of your MFA device
|
||||
- TOTP (Time-Based One-Time Password)
|
||||
|
||||
## STS Endpoint Region
|
||||
|
||||
If you are using Prowler in AWS regions that are not enabled by default you need to use the argument `--sts-endpoint-region` to point the AWS STS API calls `assume-role` and `get-caller-identity` to the non-default region, e.g.: `prowler aws --sts-endpoint-region eu-south-2`.
|
||||
34
docs/tutorials/aws/boto3-configuration.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Boto3 Retrier Configuration
|
||||
|
||||
Prowler's AWS Provider uses the Boto3 [Standard](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/retries.html) retry mode to assist in retrying client calls to AWS services when these kinds of errors or exceptions are experienced. This mode includes the following behaviours:
|
||||
|
||||
- A default value of 3 for maximum retry attempts. This can be overwritten with the `--aws-retries-max-attempts 5` argument.
|
||||
|
||||
- Retry attempts for an expanded list of errors/exceptions:
|
||||
```
|
||||
# Transient errors/exceptions
|
||||
RequestTimeout
|
||||
RequestTimeoutException
|
||||
PriorRequestNotComplete
|
||||
ConnectionError
|
||||
HTTPClientError
|
||||
|
||||
# Service-side throttling/limit errors and exceptions
|
||||
Throttling
|
||||
ThrottlingException
|
||||
ThrottledException
|
||||
RequestThrottledException
|
||||
TooManyRequestsException
|
||||
ProvisionedThroughputExceededException
|
||||
TransactionInProgressException
|
||||
RequestLimitExceeded
|
||||
BandwidthLimitExceeded
|
||||
LimitExceededException
|
||||
RequestThrottled
|
||||
SlowDown
|
||||
EC2ThrottledException
|
||||
```
|
||||
|
||||
- Retry attempts on nondescriptive, transient error codes. Specifically, these HTTP status codes: 500, 502, 503, 504.
|
||||
|
||||
- Any retry attempt will include an exponential backoff by a base factor of 2 for a maximum backoff time of 20 seconds.
|
||||
@@ -1,6 +1,6 @@
|
||||
# AWS CloudShell
|
||||
|
||||
Prowler can be easely executed in AWS CloudShell but it has some prerequsites to be able to to so. AWS CloudShell is a container running with `Amazon Linux release 2 (Karoo)` that comes with Python 3.7, since Prowler requires Python >= 3.9 we need to first install a newer version of Python. Follow the steps below to successfully execute Prowler v3 in AWS CloudShell:
|
||||
Prowler can be easily executed in AWS CloudShell but it has some prerequisites to be able to to so. AWS CloudShell is a container running with `Amazon Linux release 2 (Karoo)` that comes with Python 3.7, since Prowler requires Python >= 3.9 we need to first install a newer version of Python. Follow the steps below to successfully execute Prowler v3 in AWS CloudShell:
|
||||
|
||||
- First install all dependences and then Python, in this case we need to compile it because there is not a package available at the time this document is written:
|
||||
```
|
||||
@@ -15,7 +15,7 @@ cd
|
||||
```
|
||||
- Once Python 3.9 is available we can install Prowler from pip:
|
||||
```
|
||||
pip3.9 install prowler-cloud
|
||||
pip3.9 install prowler
|
||||
```
|
||||
- Now enjoy Prowler:
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Scan Multiple AWS Accounts
|
||||
|
||||
Prowler can scan multiple accounts when it is ejecuted from one account that can assume a role in those given accounts to scan using [Assume Role feature](role-assumption.md) and [AWS Organizations integration feature](organizations.md).
|
||||
Prowler can scan multiple accounts when it is executed from one account that can assume a role in those given accounts to scan using [Assume Role feature](role-assumption.md) and [AWS Organizations integration feature](organizations.md).
|
||||
|
||||
|
||||
## Scan multiple specific accounts sequentially
|
||||
@@ -41,7 +41,7 @@ for accountId in $ACCOUNTS_LIST; do
|
||||
done
|
||||
```
|
||||
|
||||
## Scan mutiple accounts from AWS Organizations in parallel
|
||||
## Scan multiple accounts from AWS Organizations in parallel
|
||||
|
||||
- Declare a variable with all the accounts to scan. To do so, get the list of your AWS accounts in your AWS Organization by running the following command (will create a variable with all your ACTIVE accounts). Remember to run that command with the permissions needed to get that information in your AWS Organizations Management account.
|
||||
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
# AWS Organizations
|
||||
## Get AWS Account details from your AWS Organization:
|
||||
## Get AWS Account details from your AWS Organization
|
||||
|
||||
Prowler allows you to get additional information of the scanned account in CSV and JSON outputs. When scanning a single account you get the Account ID as part of the output.
|
||||
|
||||
If you have AWS Organizations Prowler can get your account details like Account Name, Email, ARN, Organization ID and Tags and you will have them next to every finding in the CSV and JSON outputs.
|
||||
|
||||
- In order to do that you can use the option `-O`/`--organizations-role <organizations_role_arn>`. See the following sample command:
|
||||
In order to do that you can use the option `-O`/`--organizations-role <organizations_role_arn>`. See the following sample command:
|
||||
|
||||
```shell
|
||||
prowler aws \
|
||||
-O arn:aws:iam::<management_organizations_account_id>:role/<role_name>
|
||||
```
|
||||
prowler aws -O arn:aws:iam::<management_organizations_account_id>:role/<role_name>
|
||||
```
|
||||
> Make sure the role in your AWS Organizatiosn management account has the permissions `organizations:ListAccounts*` and `organizations:ListTagsForResource`.
|
||||
> Make sure the role in your AWS Organizations management account has the permissions `organizations:ListAccounts*` and `organizations:ListTagsForResource`.
|
||||
|
||||
- In that command Prowler will scan the account and getting the account details from the AWS Organizations management account assuming a role and creating two reports with those details in JSON and CSV.
|
||||
In that command Prowler will scan the account and getting the account details from the AWS Organizations management account assuming a role and creating two reports with those details in JSON and CSV.
|
||||
|
||||
In the JSON output below (redacted) you can see tags coded in base64 to prevent breaking CSV or JSON due to its format:
|
||||
|
||||
@@ -30,20 +31,28 @@ The additional fields in CSV header output are as follow:
|
||||
ACCOUNT_DETAILS_EMAIL,ACCOUNT_DETAILS_NAME,ACCOUNT_DETAILS_ARN,ACCOUNT_DETAILS_ORG,ACCOUNT_DETAILS_TAGS
|
||||
```
|
||||
|
||||
## Assume Role and across all accounts in AWS Organizations or just a list of accounts:
|
||||
## Extra: run Prowler across all accounts in AWS Organizations by assuming roles
|
||||
|
||||
If you want to run Prowler across all accounts of AWS Organizations you can do this:
|
||||
|
||||
- First get a list of accounts that are not suspended:
|
||||
1. First get a list of accounts that are not suspended:
|
||||
|
||||
```
|
||||
ACCOUNTS_IN_ORGS=$(aws organizations list-accounts --query Accounts[?Status==`ACTIVE`].Id --output text)
|
||||
```
|
||||
```shell
|
||||
ACCOUNTS_IN_ORGS=$(aws organizations list-accounts \
|
||||
--query "Accounts[?Status=='ACTIVE'].Id" \
|
||||
--output text \
|
||||
)
|
||||
```
|
||||
|
||||
- Then run Prowler to assume a role (same in all members) per each account, in this example it is just running one particular check:
|
||||
2. Then run Prowler to assume a role (same in all members) per each account:
|
||||
|
||||
```
|
||||
for accountId in $ACCOUNTS_IN_ORGS; do prowler aws -O arn:aws:iam::<management_organizations_account_id>:role/<role_name>; done
|
||||
```
|
||||
```shell
|
||||
for accountId in $ACCOUNTS_IN_ORGS;
|
||||
do
|
||||
prowler aws \
|
||||
-O arn:aws:iam::<management_organizations_account_id>:role/<role_name> \
|
||||
-R arn:aws:iam::"${accountId}":role/<role_name>;
|
||||
done
|
||||
```
|
||||
|
||||
- Using the same for loop it can be scanned a list of accounts with a variable like `ACCOUNTS_LIST='11111111111 2222222222 333333333'`
|
||||
> Using the same for loop it can be scanned a list of accounts with a variable like `ACCOUNTS_LIST='11111111111 2222222222 333333333'`
|
||||
|
||||
81
docs/tutorials/aws/regions-and-partitions.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# AWS Regions and Partitions
|
||||
|
||||
By default Prowler is able to scan the following AWS partitions:
|
||||
|
||||
- Commercial: `aws`
|
||||
- China: `aws-cn`
|
||||
- GovCloud (US): `aws-us-gov`
|
||||
|
||||
> To check the available regions for each partition and service please refer to the following document [aws_regions_by_service.json](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/aws/aws_regions_by_service.json)
|
||||
|
||||
It is important to take into consideration that to scan the China (`aws-cn`) or GovCloud (`aws-us-gov`) partitions it is either required to have a valid region for that partition in your AWS credentials or to specify the regions you want to audit for that partition using the `-f/--region` flag.
|
||||
> Please, refer to https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials for more information about the AWS credentials configuration.
|
||||
|
||||
You can get more information about the available partitions and regions in the following [Botocore](https://github.com/boto/botocore) [file](https://github.com/boto/botocore/blob/22a19ea7c4c2c4dd7df4ab8c32733cba0c7597a4/botocore/data/partitions.json).
|
||||
## AWS China
|
||||
|
||||
To scan your AWS account in the China partition (`aws-cn`):
|
||||
|
||||
- Using the `-f/--region` flag:
|
||||
```
|
||||
prowler aws --region cn-north-1 cn-northwest-1
|
||||
```
|
||||
- Using the region configured in your AWS profile at `~/.aws/credentials` or `~/.aws/config`:
|
||||
```
|
||||
[default]
|
||||
aws_access_key_id = XXXXXXXXXXXXXXXXXXX
|
||||
aws_secret_access_key = XXXXXXXXXXXXXXXXXXX
|
||||
region = cn-north-1
|
||||
```
|
||||
> With this option all the partition regions will be scanned without the need of use the `-f/--region` flag
|
||||
|
||||
|
||||
## AWS GovCloud (US)
|
||||
|
||||
To scan your AWS account in the GovCloud (US) partition (`aws-us-gov`):
|
||||
|
||||
- Using the `-f/--region` flag:
|
||||
```
|
||||
prowler aws --region us-gov-east-1 us-gov-west-1
|
||||
```
|
||||
- Using the region configured in your AWS profile at `~/.aws/credentials` or `~/.aws/config`:
|
||||
```
|
||||
[default]
|
||||
aws_access_key_id = XXXXXXXXXXXXXXXXXXX
|
||||
aws_secret_access_key = XXXXXXXXXXXXXXXXXXX
|
||||
region = us-gov-east-1
|
||||
```
|
||||
> With this option all the partition regions will be scanned without the need of use the `-f/--region` flag
|
||||
|
||||
|
||||
## AWS ISO (US & Europe)
|
||||
|
||||
For the AWS ISO partitions, which are known as "secret partitions" and are air-gapped from the Internet, there is no builtin way to scan it. If you want to audit an AWS account in one of the AWS ISO partitions you should manually update the [aws_regions_by_service.json](https://github.com/prowler-cloud/prowler/blob/master/prowler/providers/aws/aws_regions_by_service.json) and include the partition, region and services, e.g.:
|
||||
```json
|
||||
"iam": {
|
||||
"regions": {
|
||||
"aws": [
|
||||
"eu-west-1",
|
||||
"us-east-1",
|
||||
],
|
||||
"aws-cn": [
|
||||
"cn-north-1",
|
||||
"cn-northwest-1"
|
||||
],
|
||||
"aws-us-gov": [
|
||||
"us-gov-east-1",
|
||||
"us-gov-west-1"
|
||||
],
|
||||
"aws-iso": [
|
||||
"aws-iso-global",
|
||||
"us-iso-east-1",
|
||||
"us-iso-west-1"
|
||||
],
|
||||
"aws-iso-b": [
|
||||
"aws-iso-b-global",
|
||||
"us-isob-east-1"
|
||||
],
|
||||
"aws-iso-e": [],
|
||||
}
|
||||
},
|
||||
```
|
||||
9
docs/tutorials/aws/resource-arn-based-scan.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Resource ARNs based Scan
|
||||
|
||||
Prowler allows you to scan only the resources with specific AWS Resource ARNs. This can be done with the flag `--resource-arn` followed by one or more [Amazon Resource Names (ARNs)](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) separated by space:
|
||||
|
||||
```
|
||||
prowler aws --resource-arn arn:aws:iam::012345678910:user/test arn:aws:ec2:us-east-1:123456789012:vpc/vpc-12345678
|
||||
```
|
||||
|
||||
This example will only scan the two resources with those ARNs.
|
||||
@@ -5,6 +5,13 @@ Prowler uses the AWS SDK (Boto3) underneath so it uses the same authentication m
|
||||
However, there are few ways to run Prowler against multiple accounts using IAM Assume Role feature depending on each use case:
|
||||
|
||||
1. You can just set up your custom profile inside `~/.aws/config` with all needed information about the role to assume then call it with `prowler aws -p/--profile your-custom-profile`.
|
||||
- An example profile that performs role-chaining is given below. The `credential_source` can either be set to `Environment`, `Ec2InstanceMetadata`, or `EcsContainer`.
|
||||
- Alternatively, you could use the `source_profile` instead of `credential_source` to specify a separate named profile that contains IAM user credentials with permission to assume the target the role. More information can be found [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-role.html).
|
||||
```
|
||||
[profile crossaccountrole]
|
||||
role_arn = arn:aws:iam::234567890123:role/SomeRole
|
||||
credential_source = EcsContainer
|
||||
```
|
||||
|
||||
2. You can use `-R`/`--role <role_arn>` and Prowler will get those temporary credentials using `Boto3` and run against that given account.
|
||||
```sh
|
||||
@@ -16,10 +23,21 @@ prowler aws -R arn:aws:iam::<account_id>:role/<role_name>
|
||||
prowler aws -T/--session-duration <seconds> -I/--external-id <external_id> -R arn:aws:iam::<account_id>:role/<role_name>
|
||||
```
|
||||
|
||||
## STS Endpoint Region
|
||||
|
||||
If you are using Prowler in AWS regions that are not enabled by default you need to use the argument `--sts-endpoint-region` to point the AWS STS API calls `assume-role` and `get-caller-identity` to the non-default region, e.g.: `prowler aws --sts-endpoint-region eu-south-2`.
|
||||
|
||||
## Role MFA
|
||||
|
||||
If your IAM Role has MFA configured you can use `--mfa` along with `-R`/`--role <role_arn>` and Prowler will ask you to input the following values to get a new temporary session for the IAM Role provided:
|
||||
|
||||
- ARN of your MFA device
|
||||
- TOTP (Time-Based One-Time Password)
|
||||
|
||||
## Create Role
|
||||
|
||||
To create a role to be assumed in one or multiple accounts you can use either as CloudFormation Stack or StackSet the following [template](https://github.com/prowler-cloud/prowler/blob/master/permissions/create_role_to_assume_cfn.yaml) and adapt it.
|
||||
|
||||
> _NOTE 1 about Session Duration_: Depending on the mount of checks you run and the size of your infrastructure, Prowler may require more than 1 hour to finish. Use option `-T <seconds>` to allow up to 12h (43200 seconds). To allow more than 1h you need to modify _"Maximum CLI/API session duration"_ for that particular role, read more [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session).
|
||||
> _NOTE 1 about Session Duration_: Depending on the amount of checks you run and the size of your infrastructure, Prowler may require more than 1 hour to finish. Use option `-T <seconds>` to allow up to 12h (43200 seconds). To allow more than 1h you need to modify _"Maximum CLI/API session duration"_ for that particular role, read more [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session).
|
||||
|
||||
> _NOTE 2 about Session Duration_: Bear in mind that if you are using roles assumed by role chaining there is a hard limit of 1 hour so consider not using role chaining if possible, read more about that, in foot note 1 below the table [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html).
|
||||
|
||||
26
docs/tutorials/aws/s3.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Send report to AWS S3 Bucket
|
||||
|
||||
To save your report in an S3 bucket, use `-B`/`--output-bucket`.
|
||||
|
||||
```sh
|
||||
prowler <provider> -B my-bucket
|
||||
```
|
||||
|
||||
If you can use a custom folder and/or filename, use `-o`/`--output-directory` and/or `-F`/`--output-filename`.
|
||||
|
||||
```sh
|
||||
prowler <provider> \
|
||||
-B my-bucket \
|
||||
--output-directory test-folder \
|
||||
--output-filename output-filename
|
||||
```
|
||||
|
||||
By default Prowler sends HTML, JSON and CSV output formats, if you want to send a custom output format or a single one of the defaults you can specify it with the `-M`/`--output-modes` flag.
|
||||
|
||||
```sh
|
||||
prowler <provider> -M csv -B my-bucket
|
||||
```
|
||||
|
||||
> In the case you do not want to use the assumed role credentials but the initial credentials to put the reports into the S3 bucket, use `-D`/`--output-bucket-no-assume` instead of `-B`/`--output-bucket`.
|
||||
|
||||
> Make sure that the used credentials have `s3:PutObject` permissions in the S3 path where the reports are going to be uploaded.
|
||||
@@ -13,26 +13,55 @@ Before sending findings to Prowler, you will need to perform next steps:
|
||||
- Using the AWS Management Console:
|
||||

|
||||
3. Allow Prowler to import its findings to AWS Security Hub by adding the policy below to the role or user running Prowler:
|
||||
- [prowler-security-hub.json](https://github.com/prowler-cloud/prowler/blob/master/iam/prowler-security-hub.json)
|
||||
- [prowler-security-hub.json](https://github.com/prowler-cloud/prowler/blob/master/permissions/prowler-security-hub.json)
|
||||
|
||||
Once it is enabled, it is as simple as running the command below (for all regions):
|
||||
|
||||
```sh
|
||||
./prowler aws -S
|
||||
prowler aws -S
|
||||
```
|
||||
|
||||
or for only one filtered region like eu-west-1:
|
||||
|
||||
```sh
|
||||
./prowler -S -f eu-west-1
|
||||
prowler -S -f eu-west-1
|
||||
```
|
||||
|
||||
> **Note 1**: It is recommended to send only fails to Security Hub and that is possible adding `-q` to the command.
|
||||
|
||||
> **Note 2**: Since Prowler perform checks to all regions by defauls you may need to filter by region when runing Security Hub integration, as shown in the example above. Remember to enable Security Hub in the region or regions you need by calling `aws securityhub enable-security-hub --region <region>` and run Prowler with the option `-f <region>` (if no region is used it will try to push findings in all regions hubs).
|
||||
> **Note 2**: Since Prowler perform checks to all regions by default you may need to filter by region when running Security Hub integration, as shown in the example above. Remember to enable Security Hub in the region or regions you need by calling `aws securityhub enable-security-hub --region <region>` and run Prowler with the option `-f <region>` (if no region is used it will try to push findings in all regions hubs). Prowler will send findings to the Security Hub on the region where the scanned resource is located.
|
||||
|
||||
> **Note 3** to have updated findings in Security Hub you have to run Prowler periodically. Once a day or every certain amount of hours.
|
||||
> **Note 3**: To have updated findings in Security Hub you have to run Prowler periodically. Once a day or every certain amount of hours.
|
||||
|
||||
Once you run findings for first time you will be able to see Prowler findings in Findings section:
|
||||
|
||||

|
||||
|
||||
## Send findings to Security Hub assuming an IAM Role
|
||||
|
||||
When you are auditing a multi-account AWS environment, you can send findings to a Security Hub of another account by assuming an IAM role from that account using the `-R` flag in the Prowler command:
|
||||
|
||||
```sh
|
||||
prowler -S -R arn:aws:iam::123456789012:role/ProwlerExecRole
|
||||
```
|
||||
|
||||
> Remember that the used role needs to have permissions to send findings to Security Hub. To get more information about the permissions required, please refer to the following IAM policy [prowler-security-hub.json](https://github.com/prowler-cloud/prowler/blob/master/permissions/prowler-security-hub.json)
|
||||
|
||||
|
||||
## Send only failed findings to Security Hub
|
||||
|
||||
When using Security Hub it is recommended to send only the failed findings generated. To follow that recommendation you could add the `-q` flag to the Prowler command:
|
||||
|
||||
```sh
|
||||
prowler -S -q
|
||||
```
|
||||
|
||||
|
||||
## Skip sending updates of findings to Security Hub
|
||||
|
||||
By default, Prowler archives all its findings in Security Hub that have not appeared in the last scan.
|
||||
You can skip this logic by using the option `--skip-sh-update` so Prowler will not archive older findings:
|
||||
|
||||
```sh
|
||||
prowler -S --skip-sh-update
|
||||
```
|
||||
|
||||
9
docs/tutorials/aws/tag-based-scan.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Tags-based Scan
|
||||
|
||||
Prowler allows you to scan only the resources that contain specific tags. This can be done with the flag `--resource-tags` followed by the tags `Key=Value` separated by space:
|
||||
|
||||
```
|
||||
prowler aws --resource-tags Environment=dev Project=prowler
|
||||
```
|
||||
|
||||
This example will only scan the resources that contains both tags.
|
||||
255
docs/tutorials/aws/v2_to_v3_checks_mapping.md
Normal file
@@ -0,0 +1,255 @@
|
||||
# Check mapping between Prowler v3 and v2
|
||||
|
||||
Prowler v3 comes with different identifiers but we maintained the same checks that were implemented in v2. The reason for this change is because in previous versions of Prowler, check names were mostly based on CIS Benchmark for AWS. In v3 all checks are independent from any security framework and they have its own name and ID.
|
||||
|
||||
If you need more information about how new compliance implementation works in Prowler v3 see [Compliance](../compliance.md) section.
|
||||
|
||||
```
|
||||
checks_v3_to_v2_mapping = {
|
||||
"accessanalyzer_enabled_without_findings": "extra769",
|
||||
"account_maintain_current_contact_details": "check117",
|
||||
"account_security_contact_information_is_registered": "check118",
|
||||
"account_security_questions_are_registered_in_the_aws_account": "check115",
|
||||
"acm_certificates_expiration_check": "extra730",
|
||||
"acm_certificates_transparency_logs_enabled": "extra724",
|
||||
"apigateway_authorizers_enabled": "extra746",
|
||||
"apigateway_client_certificate_enabled": "extra743",
|
||||
"apigateway_endpoint_public": "extra745",
|
||||
"apigateway_logging_enabled": "extra722",
|
||||
"apigateway_waf_acl_attached": "extra744",
|
||||
"apigatewayv2_access_logging_enabled": "extra7156",
|
||||
"apigatewayv2_authorizers_enabled": "extra7157",
|
||||
"appstream_fleet_default_internet_access_disabled": "extra7193",
|
||||
"appstream_fleet_maximum_session_duration": "extra7190",
|
||||
"appstream_fleet_session_disconnect_timeout": "extra7191",
|
||||
"appstream_fleet_session_idle_disconnect_timeout": "extra7192",
|
||||
"autoscaling_find_secrets_ec2_launch_configuration": "extra775",
|
||||
"awslambda_function_invoke_api_operations_cloudtrail_logging_enabled": "extra720",
|
||||
"awslambda_function_no_secrets_in_code": "extra760",
|
||||
"awslambda_function_no_secrets_in_variables": "extra759",
|
||||
"awslambda_function_not_publicly_accessible": "extra798",
|
||||
"awslambda_function_url_cors_policy": "extra7180",
|
||||
"awslambda_function_url_public": "extra7179",
|
||||
"awslambda_function_using_supported_runtimes": "extra762",
|
||||
"cloudformation_stack_outputs_find_secrets": "extra742",
|
||||
"cloudformation_stacks_termination_protection_enabled": "extra7154",
|
||||
"cloudfront_distributions_field_level_encryption_enabled": "extra767",
|
||||
"cloudfront_distributions_geo_restrictions_enabled": "extra732",
|
||||
"cloudfront_distributions_https_enabled": "extra738",
|
||||
"cloudfront_distributions_logging_enabled": "extra714",
|
||||
"cloudfront_distributions_using_deprecated_ssl_protocols": "extra791",
|
||||
"cloudfront_distributions_using_waf": "extra773",
|
||||
"cloudtrail_cloudwatch_logging_enabled": "check24",
|
||||
"cloudtrail_kms_encryption_enabled": "check27",
|
||||
"cloudtrail_log_file_validation_enabled": "check22",
|
||||
"cloudtrail_logs_s3_bucket_access_logging_enabled": "check26",
|
||||
"cloudtrail_logs_s3_bucket_is_not_publicly_accessible": "check23",
|
||||
"cloudtrail_multi_region_enabled": "check21",
|
||||
"cloudtrail_s3_dataevents_read_enabled": "extra7196",
|
||||
"cloudtrail_s3_dataevents_write_enabled": "extra725",
|
||||
"cloudwatch_changes_to_network_acls_alarm_configured": "check311",
|
||||
"cloudwatch_changes_to_network_gateways_alarm_configured": "check312",
|
||||
"cloudwatch_changes_to_network_route_tables_alarm_configured": "check313",
|
||||
"cloudwatch_changes_to_vpcs_alarm_configured": "check314",
|
||||
"cloudwatch_cross_account_sharing_disabled": "extra7144",
|
||||
"cloudwatch_log_group_kms_encryption_enabled": "extra7164",
|
||||
"cloudwatch_log_group_retention_policy_specific_days_enabled": "extra7162",
|
||||
"cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled": "check39",
|
||||
"cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled": "check35",
|
||||
"cloudwatch_log_metric_filter_authentication_failures": "check36",
|
||||
"cloudwatch_log_metric_filter_aws_organizations_changes": "extra7197",
|
||||
"cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk": "check37",
|
||||
"cloudwatch_log_metric_filter_for_s3_bucket_policy_changes": "check38",
|
||||
"cloudwatch_log_metric_filter_policy_changes": "check34",
|
||||
"cloudwatch_log_metric_filter_root_usage": "check33",
|
||||
"cloudwatch_log_metric_filter_security_group_changes": "check310",
|
||||
"cloudwatch_log_metric_filter_sign_in_without_mfa": "check32",
|
||||
"cloudwatch_log_metric_filter_unauthorized_api_calls": "check31",
|
||||
"codeartifact_packages_external_public_publishing_disabled": "extra7195",
|
||||
"codebuild_project_older_90_days": "extra7174",
|
||||
"codebuild_project_user_controlled_buildspec": "extra7175",
|
||||
"config_recorder_all_regions_enabled": "check25",
|
||||
"directoryservice_directory_log_forwarding_enabled": "extra7181",
|
||||
"directoryservice_directory_monitor_notifications": "extra7182",
|
||||
"directoryservice_directory_snapshots_limit": "extra7184",
|
||||
"directoryservice_ldap_certificate_expiration": "extra7183",
|
||||
"directoryservice_radius_server_security_protocol": "extra7188",
|
||||
"directoryservice_supported_mfa_radius_enabled": "extra7189",
|
||||
"dynamodb_accelerator_cluster_encryption_enabled": "extra7165",
|
||||
"dynamodb_tables_kms_cmk_encryption_enabled": "extra7128",
|
||||
"dynamodb_tables_pitr_enabled": "extra7151",
|
||||
"ec2_ami_public": "extra76",
|
||||
"ec2_ebs_default_encryption": "extra761",
|
||||
"ec2_ebs_public_snapshot": "extra72",
|
||||
"ec2_ebs_snapshots_encrypted": "extra740",
|
||||
"ec2_ebs_volume_encryption": "extra729",
|
||||
"ec2_elastic_ip_shodan": "extra7102",
|
||||
"ec2_elastic_ip_unassgined": "extra7146",
|
||||
"ec2_instance_imdsv2_enabled": "extra786",
|
||||
"ec2_instance_internet_facing_with_instance_profile": "extra770",
|
||||
"ec2_instance_managed_by_ssm": "extra7124",
|
||||
"ec2_instance_older_than_specific_days": "extra758",
|
||||
"ec2_instance_profile_attached": "check119",
|
||||
"ec2_instance_public_ip": "extra710",
|
||||
"ec2_instance_secrets_user_data": "extra741",
|
||||
"ec2_networkacl_allow_ingress_any_port": "extra7138",
|
||||
"ec2_networkacl_allow_ingress_tcp_port_22": "check45",
|
||||
"ec2_networkacl_allow_ingress_tcp_port_3389": "check46",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_any_port": "extra748",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018": "extra753",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21": "extra7134",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22": "check41",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389": "check42",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888": "extra754",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601": "extra779",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092": "extra7135",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211": "extra755",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306": "extra750",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483": "extra749",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432": "extra751",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379": "extra752",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434": "extra7137",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23": "extra7136",
|
||||
"ec2_securitygroup_allow_wide_open_public_ipv4": "extra778",
|
||||
"ec2_securitygroup_default_restrict_traffic": "check43",
|
||||
"ec2_securitygroup_from_launch_wizard": "extra7173",
|
||||
"ec2_securitygroup_not_used": "extra75",
|
||||
"ec2_securitygroup_with_many_ingress_egress_rules": "extra777",
|
||||
"ecr_repositories_lifecycle_policy_enabled": "extra7194",
|
||||
"ecr_repositories_not_publicly_accessible": "extra77",
|
||||
"ecr_repositories_scan_images_on_push_enabled": "extra765",
|
||||
"ecr_repositories_scan_vulnerabilities_in_latest_image": "extra776",
|
||||
"ecs_task_definitions_no_environment_secrets": "extra768",
|
||||
"efs_encryption_at_rest_enabled": "extra7161",
|
||||
"efs_have_backup_enabled": "extra7148",
|
||||
"efs_not_publicly_accessible": "extra7143",
|
||||
"eks_cluster_kms_cmk_encryption_in_secrets_enabled": "extra797",
|
||||
"eks_control_plane_endpoint_access_restricted": "extra796",
|
||||
"eks_control_plane_logging_all_types_enabled": "extra794",
|
||||
"eks_endpoints_not_publicly_accessible": "extra795",
|
||||
"elb_insecure_ssl_ciphers": "extra792",
|
||||
"elb_internet_facing": "extra79",
|
||||
"elb_logging_enabled": "extra717",
|
||||
"elb_ssl_listeners": "extra793",
|
||||
"elbv2_deletion_protection": "extra7150",
|
||||
"elbv2_desync_mitigation_mode": "extra7155",
|
||||
"elbv2_insecure_ssl_ciphers": "extra792",
|
||||
"elbv2_internet_facing": "extra79",
|
||||
"elbv2_listeners_underneath": "extra7158",
|
||||
"elbv2_logging_enabled": "extra717",
|
||||
"elbv2_ssl_listeners": "extra793",
|
||||
"elbv2_waf_acl_attached": "extra7129",
|
||||
"emr_cluster_account_public_block_enabled": "extra7178",
|
||||
"emr_cluster_master_nodes_no_public_ip": "extra7176",
|
||||
"emr_cluster_publicly_accesible": "extra7177",
|
||||
"glacier_vaults_policy_public_access": "extra7147",
|
||||
"glue_data_catalogs_connection_passwords_encryption_enabled": "extra7117",
|
||||
"glue_data_catalogs_metadata_encryption_enabled": "extra7116",
|
||||
"glue_database_connections_ssl_enabled": "extra7115",
|
||||
"glue_development_endpoints_cloudwatch_logs_encryption_enabled": "extra7119",
|
||||
"glue_development_endpoints_job_bookmark_encryption_enabled": "extra7121",
|
||||
"glue_development_endpoints_s3_encryption_enabled": "extra7114",
|
||||
"glue_etl_jobs_amazon_s3_encryption_enabled": "extra7118",
|
||||
"glue_etl_jobs_cloudwatch_logs_encryption_enabled": "extra7120",
|
||||
"glue_etl_jobs_job_bookmark_encryption_enabled": "extra7122",
|
||||
"guardduty_is_enabled": "extra713",
|
||||
"guardduty_no_high_severity_findings": "extra7139",
|
||||
"iam_administrator_access_with_mfa": "extra71",
|
||||
"iam_avoid_root_usage": "check11",
|
||||
"iam_check_saml_providers_sts": "extra733",
|
||||
"iam_disable_30_days_credentials": "extra774",
|
||||
"iam_disable_45_days_credentials": "extra7198",
|
||||
"iam_disable_90_days_credentials": "check13",
|
||||
"iam_no_custom_policy_permissive_role_assumption": "extra7100",
|
||||
"iam_no_expired_server_certificates_stored": "extra7199",
|
||||
"iam_no_root_access_key": "check112",
|
||||
"iam_password_policy_expires_passwords_within_90_days_or_less": "check111",
|
||||
"iam_password_policy_lowercase": "check16",
|
||||
"iam_password_policy_minimum_length_14": "check19",
|
||||
"iam_password_policy_number": "check18",
|
||||
"iam_password_policy_reuse_24": "check110",
|
||||
"iam_password_policy_symbol": "check17",
|
||||
"iam_password_policy_uppercase": "check15",
|
||||
"iam_policy_allows_privilege_escalation": "extra7185",
|
||||
"iam_policy_attached_only_to_group_or_roles": "check116",
|
||||
"iam_policy_no_administrative_privileges": "check122",
|
||||
"iam_root_hardware_mfa_enabled": "check114",
|
||||
"iam_root_mfa_enabled": "check113",
|
||||
"iam_rotate_access_key_90_days": "check14",
|
||||
"iam_support_role_created": "check120",
|
||||
"iam_user_hardware_mfa_enabled": "extra7125",
|
||||
"iam_user_mfa_enabled_console_access": "check12",
|
||||
"iam_user_no_setup_initial_access_key": "check121",
|
||||
"iam_user_two_active_access_key": "extra7123",
|
||||
"iam_role_cross_service_confused_deputy_prevention": "extra7201",
|
||||
"kms_cmk_are_used": "extra7126",
|
||||
"kms_cmk_rotation_enabled": "check28",
|
||||
"kms_key_not_publicly_accessible": "extra736",
|
||||
"macie_is_enabled": "extra712",
|
||||
"opensearch_service_domains_audit_logging_enabled": "extra7101",
|
||||
"opensearch_service_domains_cloudwatch_logging_enabled": "extra715",
|
||||
"opensearch_service_domains_encryption_at_rest_enabled": "extra781",
|
||||
"opensearch_service_domains_https_communications_enforced": "extra783",
|
||||
"opensearch_service_domains_internal_user_database_enabled": "extra784",
|
||||
"opensearch_service_domains_node_to_node_encryption_enabled": "extra782",
|
||||
"opensearch_service_domains_not_publicly_accessible": "extra716",
|
||||
"opensearch_service_domains_updated_to_the_latest_service_software_version": "extra785",
|
||||
"opensearch_service_domains_use_cognito_authentication_for_kibana": "extra780",
|
||||
"rds_instance_backup_enabled": "extra739",
|
||||
"rds_instance_deletion_protection": "extra7113",
|
||||
"rds_instance_enhanced_monitoring_enabled": "extra7132",
|
||||
"rds_instance_integration_cloudwatch_logs": "extra747",
|
||||
"rds_instance_minor_version_upgrade_enabled": "extra7131",
|
||||
"rds_instance_multi_az": "extra7133",
|
||||
"rds_instance_no_public_access": "extra78",
|
||||
"rds_instance_storage_encrypted": "extra735",
|
||||
"rds_snapshots_public_access": "extra723",
|
||||
"redshift_cluster_audit_logging": "extra721",
|
||||
"redshift_cluster_automated_snapshot": "extra7149",
|
||||
"redshift_cluster_automatic_upgrades": "extra7160",
|
||||
"redshift_cluster_public_access": "extra711",
|
||||
"route53_domains_privacy_protection_enabled": "extra7152",
|
||||
"route53_domains_transferlock_enabled": "extra7153",
|
||||
"route53_public_hosted_zones_cloudwatch_logging_enabled": "extra719",
|
||||
"s3_account_level_public_access_blocks": "extra7186",
|
||||
"s3_bucket_acl_prohibited": "extra7172",
|
||||
"s3_bucket_default_encryption": "extra734",
|
||||
"s3_bucket_no_mfa_delete": "extra7200",
|
||||
"s3_bucket_object_versioning": "extra763",
|
||||
"s3_bucket_policy_public_write_access": "extra771",
|
||||
"s3_bucket_public_access": "extra73",
|
||||
"s3_bucket_secure_transport_policy": "extra764",
|
||||
"s3_bucket_server_access_logging_enabled": "extra718",
|
||||
"sagemaker_models_network_isolation_enabled": "extra7105",
|
||||
"sagemaker_models_vpc_settings_configured": "extra7106",
|
||||
"sagemaker_notebook_instance_encryption_enabled": "extra7112",
|
||||
"sagemaker_notebook_instance_root_access_disabled": "extra7103",
|
||||
"sagemaker_notebook_instance_vpc_settings_configured": "extra7104",
|
||||
"sagemaker_notebook_instance_without_direct_internet_access_configured": "extra7111",
|
||||
"sagemaker_training_jobs_intercontainer_encryption_enabled": "extra7107",
|
||||
"sagemaker_training_jobs_network_isolation_enabled": "extra7109",
|
||||
"sagemaker_training_jobs_volume_and_output_encryption_enabled": "extra7108",
|
||||
"sagemaker_training_jobs_vpc_settings_configured": "extra7110",
|
||||
"secretsmanager_automatic_rotation_enabled": "extra7163",
|
||||
"securityhub_enabled": "extra799",
|
||||
"shield_advanced_protection_in_associated_elastic_ips": "extra7166",
|
||||
"shield_advanced_protection_in_classic_load_balancers": "extra7171",
|
||||
"shield_advanced_protection_in_cloudfront_distributions": "extra7167",
|
||||
"shield_advanced_protection_in_global_accelerators": "extra7169",
|
||||
"shield_advanced_protection_in_internet_facing_load_balancers": "extra7170",
|
||||
"shield_advanced_protection_in_route53_hosted_zones": "extra7168",
|
||||
"sns_topics_kms_encryption_at_rest_enabled": "extra7130",
|
||||
"sns_topics_not_publicly_accessible": "extra731",
|
||||
"sqs_queues_not_publicly_accessible": "extra727",
|
||||
"sqs_queues_server_side_encryption_enabled": "extra728",
|
||||
"ssm_document_secrets": "extra7141",
|
||||
"ssm_documents_set_as_public": "extra7140",
|
||||
"ssm_managed_compliant_patching": "extra7127",
|
||||
"trustedadvisor_errors_and_warnings": "extra726",
|
||||
"vpc_endpoint_connections_trust_boundaries": "extra789",
|
||||
"vpc_endpoint_services_allowed_principals_trust_boundaries": "extra790",
|
||||
"vpc_flow_logs_enabled": "check29",
|
||||
"vpc_peering_routing_tables_with_least_privilege": "check44",
|
||||
"workspaces_volume_encryption_enabled": "extra7187",
|
||||
}
|
||||
```
|
||||
@@ -18,10 +18,10 @@ prowler azure --sp-env-auth
|
||||
prowler azure --az-cli-auth
|
||||
|
||||
# To use browser authentication
|
||||
prowler azure --browser-auth
|
||||
prowler azure --browser-auth --tenant-id "XXXXXXXX"
|
||||
|
||||
# To use managed identity auth
|
||||
prowler azure --managed-identity-auth
|
||||
```
|
||||
|
||||
To use Prowler you need to set up also the permissions required to access your resources in your Azure account, to more details refer to [Requirements](/getting-started/requirements)
|
||||
To use Prowler you need to set up also the permissions required to access your resources in your Azure account, to more details refer to [Requirements](../../getting-started/requirements.md)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Azure subscriptions scope
|
||||
|
||||
By default Prowler is multisubscription, which means that is going to scan all the subscriptions is able to list. If you only assign permissions to one subscription it is going to scan a single one.
|
||||
By default, Prowler is multisubscription, which means that is going to scan all the subscriptions is able to list. If you only assign permissions to one subscription, it is going to scan a single one.
|
||||
Prowler also has the ability to limit the subscriptions to scan to a set passed as input argument, to do so:
|
||||
|
||||
```console
|
||||
prowler azure --az-cli-auth --subscription-ids <subscription ID 1> <subscription ID 2> ... <subscription ID N>
|
||||
```
|
||||
|
||||
Where you can pass from 1 up to N subscriptions to be scanned.
|
||||
Where you can pass from 1 up to N subscriptions to be scanned.
|
||||
|
||||
@@ -11,6 +11,25 @@ Currently, the available frameworks are:
|
||||
- `cis_1.4_aws`
|
||||
- `cis_1.5_aws`
|
||||
- `ens_rd2022_aws`
|
||||
- `aws_audit_manager_control_tower_guardrails_aws`
|
||||
- `aws_foundational_security_best_practices_aws`
|
||||
- `aws_well_architected_framework_security_pillar_aws`
|
||||
- `cisa_aws`
|
||||
- `fedramp_low_revision_4_aws`
|
||||
- `fedramp_moderate_revision_4_aws`
|
||||
- `ffiec_aws`
|
||||
- `gdpr_aws`
|
||||
- `gxp_eu_annex_11_aws`
|
||||
- `gxp_21_cfr_part_11_aws`
|
||||
- `hipaa_aws`
|
||||
- `nist_800_53_revision_4_aws`
|
||||
- `nist_800_53_revision_5_aws`
|
||||
- `nist_800_171_revision_2_aws`
|
||||
- `nist_csf_1.1_aws`
|
||||
- `pci_3.2.1_aws`
|
||||
- `rbi_cyber_security_framework_aws`
|
||||
- `soc2_aws`
|
||||
|
||||
|
||||
## List Requirements of Compliance Frameworks
|
||||
For each compliance framework, you can use option `--list-compliance-requirements` to list its requirements:
|
||||
@@ -59,40 +78,8 @@ prowler <provider> --compliance <compliance_framework>
|
||||
```
|
||||
Standard results will be shown and additionally the framework information as the sample below for CIS AWS 1.5. For details a CSV file has been generated as well.
|
||||
|
||||
<img src="/img/compliance-cis-sample1.png"/>
|
||||
<img src="../img/compliance-cis-sample1.png"/>
|
||||
|
||||
## Create and contribute adding other Security Frameworks
|
||||
|
||||
If you want to create or contribute with your own security frameworks or add public ones to Prowler you need to make sure the checks are available if not you have to create your own. Then create a compliance file per provider like in `prowler/compliance/aws/` and name it as `<framework>_<version>_<provider>.json` then follow the following format to create yours.
|
||||
|
||||
Each file version of a framework will have the following structure at high level with the case that each framework needs to be generally identified), one requirement can be also called one control but one requirement can be linked to multiple prowler checks.:
|
||||
|
||||
- `Framework`: string. Indistiguish name of the framework, like CIS
|
||||
- `Provider`: string. Provider where the framework applies, such as AWS, Azure, OCI,...
|
||||
- `Version`: string. Version of the framework itself, like 1.4 for CIS.
|
||||
- `Requirements`: array of objects. Include all requirements or controls with the mapping to Prowler.
|
||||
- `Requirements_Id`: string. Unique identifier per each requirement in the specific framework
|
||||
- `Requirements_Description`: string. Description as in the framework.
|
||||
- `Requirements_Attributes`: array of objects. Includes all needed attributes per each requirement, like levels, sections, etc. Whatever helps to create a dedicated report with the result of the findings. Attributes would be taken as closely as possible from the framework's own terminology directly.
|
||||
- `Requirements_Checks`: array. Prowler checks that are needed to prove this requirement. It can be one or multiple checks. In case of no automation possible this can be empty.
|
||||
|
||||
```
|
||||
{
|
||||
"Framework": "<framework>-<provider>",
|
||||
"Version": "<version>",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "<unique-id>",
|
||||
"Description": "Requiemente full description",
|
||||
"Checks": [
|
||||
"Here is the prowler check or checks that is going to be executed"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
<Add here your custom attributes.>
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Finally, to have a proper output file for your reports, your framework data model has to be created in `prowler/lib/outputs/models.py` and also the CLI table output in `prowler/lib/outputs/compliance.py`.
|
||||
This information is part of the Developer Guide and can be found here: https://docs.prowler.cloud/en/latest/tutorials/developer-guide/.
|
||||
|
||||
@@ -1,76 +1,111 @@
|
||||
# Configuration File
|
||||
Several Prowler's checks have user configurable variables that can be modified in a common **configuration file**.
|
||||
This file can be found in the following path:
|
||||
Several Prowler's checks have user configurable variables that can be modified in a common **configuration file**. This file can be found in the following [path](https://github.com/prowler-cloud/prowler/blob/master/prowler/config/config.yaml):
|
||||
```
|
||||
prowler/config/config.yaml
|
||||
```
|
||||
|
||||
## Configurable Checks
|
||||
The following list includes all the checks with configurable variables that can be changed in the mentioned configuration yaml file:
|
||||
Also you can input a custom configuration file using the `--config-file` argument.
|
||||
|
||||
1. aws.ec2_elastic_ip_shodan
|
||||
- shodan_api_key (String)
|
||||
- aws.ec2_securitygroup_with_many_ingress_egress_rules
|
||||
- max_security_group_rules (Integer)
|
||||
- aws.ec2_instance_older_than_specific_days
|
||||
- max_ec2_instance_age_in_days (Integer)
|
||||
- aws.vpc_endpoint_connections_trust_boundaries
|
||||
- trusted_account_ids (List of Strings)
|
||||
- aws.vpc_endpoint_services_allowed_principals_trust_boundaries
|
||||
- trusted_account_ids (List of Strings)
|
||||
- aws.cloudwatch_log_group_retention_policy_specific_days_enabled
|
||||
- log_group_retention_days (Integer)
|
||||
- aws.appstream_fleet_session_idle_disconnect_timeout
|
||||
- max_idle_disconnect_timeout_in_seconds (Integer)
|
||||
- aws.appstream_fleet_session_disconnect_timeout
|
||||
- max_disconnect_timeout_in_seconds (Integer)
|
||||
- aws.appstream_fleet_maximum_session_duration
|
||||
- max_session_duration_seconds (Integer)
|
||||
- aws.awslambda_function_using_supported_runtimes
|
||||
- obsolete_lambda_runtimes (List of Strings)
|
||||
## AWS
|
||||
|
||||
## Config Yaml File
|
||||
### Configurable Checks
|
||||
The following list includes all the AWS checks with configurable variables that can be changed in the configuration yaml file:
|
||||
|
||||
# AWS EC2 Configuration
|
||||
# aws.ec2_elastic_ip_shodan
|
||||
shodan_api_key: null
|
||||
# aws.ec2_securitygroup_with_many_ingress_egress_rules --> by default is 50 rules
|
||||
max_security_group_rules: 50
|
||||
# aws.ec2_instance_older_than_specific_days --> by default is 6 months (180 days)
|
||||
max_ec2_instance_age_in_days: 180
|
||||
| Check Name | Value | Type |
|
||||
|---|---|---|
|
||||
| `ec2_elastic_ip_shodan` | `shodan_api_key` | String |
|
||||
| `ec2_securitygroup_with_many_ingress_egress_rules` | `max_security_group_rules` | Integer |
|
||||
| `ec2_instance_older_than_specific_days` | `max_ec2_instance_age_in_days` | Integer |
|
||||
| `vpc_endpoint_connections_trust_boundaries` | `trusted_account_ids` | List of Strings |
|
||||
| `vpc_endpoint_services_allowed_principals_trust_boundaries` | `trusted_account_ids` | List of Strings |
|
||||
| `cloudwatch_log_group_retention_policy_specific_days_enabled` | `log_group_retention_days` | Integer |
|
||||
| `appstream_fleet_session_idle_disconnect_timeout` | `max_idle_disconnect_timeout_in_seconds` | Integer |
|
||||
| `appstream_fleet_session_disconnect_timeout` | `max_disconnect_timeout_in_seconds` | Integer |
|
||||
| `appstream_fleet_maximum_session_duration` | `max_session_duration_seconds` | Integer |
|
||||
| `awslambda_function_using_supported_runtimes` | `obsolete_lambda_runtimes` | Integer |
|
||||
| `organizations_scp_check_deny_regions` | `organizations_enabled_regions` | List of Strings |
|
||||
| `organizations_delegated_administrators` | `organizations_trusted_delegated_administrators` | List of Strings |
|
||||
| `ecr_repositories_scan_vulnerabilities_in_latest_image` | `ecr_repository_vulnerability_minimum_severity` | String |
|
||||
|
||||
# AWS VPC Configuration (vpc_endpoint_connections_trust_boundaries, vpc_endpoint_services_allowed_principals_trust_boundaries)
|
||||
# Single account environment: No action required. The AWS account number will be automatically added by the checks.
|
||||
# Multi account environment: Any additional trusted account number should be added as a space separated list, e.g.
|
||||
# trusted_account_ids : ["123456789012", "098765432109", "678901234567"]
|
||||
trusted_account_ids: []
|
||||
## Azure
|
||||
|
||||
# AWS Cloudwatch Configuration
|
||||
# aws.cloudwatch_log_group_retention_policy_specific_days_enabled --> by default is 365 days
|
||||
log_group_retention_days: 365
|
||||
### Configurable Checks
|
||||
|
||||
# AWS AppStream Session Configuration
|
||||
# aws.appstream_fleet_session_idle_disconnect_timeout
|
||||
max_idle_disconnect_timeout_in_seconds: 600 # 10 Minutes
|
||||
# aws.appstream_fleet_session_disconnect_timeout
|
||||
max_disconnect_timeout_in_seconds: 300 # 5 Minutes
|
||||
# aws.appstream_fleet_maximum_session_duration
|
||||
max_session_duration_seconds: 36000 # 10 Hours
|
||||
## GCP
|
||||
|
||||
# AWS Lambda Configuration
|
||||
# aws.awslambda_function_using_supported_runtimes
|
||||
obsolete_lambda_runtimes:
|
||||
### Configurable Checks
|
||||
|
||||
## Config YAML File Structure
|
||||
> This is the new Prowler configuration file format. The old one without provider keys is still compatible just for the AWS provider.
|
||||
|
||||
```yaml title="config.yaml"
|
||||
# AWS Configuration
|
||||
aws:
|
||||
# AWS EC2 Configuration
|
||||
# aws.ec2_elastic_ip_shodan
|
||||
shodan_api_key: null
|
||||
# aws.ec2_securitygroup_with_many_ingress_egress_rules --> by default is 50 rules
|
||||
max_security_group_rules: 50
|
||||
# aws.ec2_instance_older_than_specific_days --> by default is 6 months (180 days)
|
||||
max_ec2_instance_age_in_days: 180
|
||||
|
||||
# AWS VPC Configuration (vpc_endpoint_connections_trust_boundaries, vpc_endpoint_services_allowed_principals_trust_boundaries)
|
||||
# Single account environment: No action required. The AWS account number will be automatically added by the checks.
|
||||
# Multi account environment: Any additional trusted account number should be added as a space separated list, e.g.
|
||||
# trusted_account_ids : ["123456789012", "098765432109", "678901234567"]
|
||||
trusted_account_ids: []
|
||||
|
||||
# AWS Cloudwatch Configuration
|
||||
# aws.cloudwatch_log_group_retention_policy_specific_days_enabled --> by default is 365 days
|
||||
log_group_retention_days: 365
|
||||
|
||||
# AWS AppStream Session Configuration
|
||||
# aws.appstream_fleet_session_idle_disconnect_timeout
|
||||
max_idle_disconnect_timeout_in_seconds: 600 # 10 Minutes
|
||||
# aws.appstream_fleet_session_disconnect_timeout
|
||||
max_disconnect_timeout_in_seconds: 300 # 5 Minutes
|
||||
# aws.appstream_fleet_maximum_session_duration
|
||||
max_session_duration_seconds: 36000 # 10 Hours
|
||||
|
||||
# AWS Lambda Configuration
|
||||
# aws.awslambda_function_using_supported_runtimes
|
||||
obsolete_lambda_runtimes:
|
||||
[
|
||||
"python3.6",
|
||||
"python2.7",
|
||||
"nodejs4.3",
|
||||
"nodejs4.3-edge",
|
||||
"nodejs6.10",
|
||||
"nodejs",
|
||||
"nodejs8.10",
|
||||
"nodejs10.x",
|
||||
"dotnetcore1.0",
|
||||
"dotnetcore2.0",
|
||||
"dotnetcore2.1",
|
||||
"ruby2.5",
|
||||
"python3.6",
|
||||
"python2.7",
|
||||
"nodejs4.3",
|
||||
"nodejs4.3-edge",
|
||||
"nodejs6.10",
|
||||
"nodejs",
|
||||
"nodejs8.10",
|
||||
"nodejs10.x",
|
||||
"dotnetcore1.0",
|
||||
"dotnetcore2.0",
|
||||
"dotnetcore2.1",
|
||||
"ruby2.5",
|
||||
]
|
||||
|
||||
# AWS Organizations
|
||||
# organizations_scp_check_deny_regions
|
||||
# organizations_enabled_regions: [
|
||||
# 'eu-central-1',
|
||||
# 'eu-west-1',
|
||||
# "us-east-1"
|
||||
# ]
|
||||
organizations_enabled_regions: []
|
||||
organizations_trusted_delegated_administrators: []
|
||||
|
||||
# AWS ECR
|
||||
# ecr_repositories_scan_vulnerabilities_in_latest_image
|
||||
# CRITICAL
|
||||
# HIGH
|
||||
# MEDIUM
|
||||
ecr_repository_vulnerability_minimum_severity: "MEDIUM"
|
||||
|
||||
# Azure Configuration
|
||||
azure:
|
||||
|
||||
# GCP Configuration
|
||||
gcp:
|
||||
|
||||
```
|
||||
|
||||
29
docs/tutorials/gcp/authentication.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# GCP authentication
|
||||
|
||||
Prowler will use by default your User Account credentials, you can configure it using:
|
||||
|
||||
- `gcloud init` to use a new account
|
||||
- `gcloud config set account <account>` to use an existing account
|
||||
|
||||
Then, obtain your access credentials using: `gcloud auth application-default login`
|
||||
|
||||
Otherwise, you can generate and download Service Account keys in JSON format (refer to https://cloud.google.com/iam/docs/creating-managing-service-account-keys) and provide the location of the file with the following argument:
|
||||
|
||||
```console
|
||||
prowler gcp --credentials-file path
|
||||
```
|
||||
|
||||
> `prowler` will scan the GCP project associated with the credentials.
|
||||
|
||||
|
||||
Prowler will follow the same credentials search as [Google authentication libraries](https://cloud.google.com/docs/authentication/application-default-credentials#search_order):
|
||||
|
||||
1. [GOOGLE_APPLICATION_CREDENTIALS environment variable](https://cloud.google.com/docs/authentication/application-default-credentials#GAC)
|
||||
2. [User credentials set up by using the Google Cloud CLI](https://cloud.google.com/docs/authentication/application-default-credentials#personal)
|
||||
3. [The attached service account, returned by the metadata server](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa)
|
||||
|
||||
Those credentials must be associated to a user or service account with proper permissions to do all checks. To make sure, add the following roles to the member associated with the credentials:
|
||||
|
||||
- Viewer
|
||||
- Security Reviewer
|
||||
- Stackdriver Account Viewer
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
BIN
docs/tutorials/img/allowlist-row.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 141 KiB |
BIN
docs/tutorials/img/create-slack-app.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
docs/tutorials/img/install-in-slack-workspace.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
docs/tutorials/img/integrate-slack-app.png
Normal file
|
After Width: | Height: | Size: 200 KiB |
BIN
docs/tutorials/img/slack-app-token.png
Normal file
|
After Width: | Height: | Size: 456 KiB |
BIN
docs/tutorials/img/slack-prowler-message.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
36
docs/tutorials/integrations.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Integrations
|
||||
|
||||
## Slack
|
||||
|
||||
Prowler can be integrated with [Slack](https://slack.com/) to send a summary of the execution having configured a Slack APP in your channel with the following command:
|
||||
|
||||
```sh
|
||||
prowler <provider> --slack
|
||||
```
|
||||
|
||||

|
||||
|
||||
> Slack integration needs SLACK_API_TOKEN and SLACK_CHANNEL_ID environment variables.
|
||||
### Configuration
|
||||
|
||||
To configure the Slack Integration, follow the next steps:
|
||||
|
||||
1. Create a Slack Application:
|
||||
- Go to [Slack API page](https://api.slack.com/tutorials/tracks/getting-a-token), scroll down to the *Create app* button and select your workspace:
|
||||

|
||||
|
||||
- Install the application in your selected workspaces:
|
||||

|
||||
|
||||
- Get the *Slack App OAuth Token* that Prowler needs to send the message:
|
||||

|
||||
|
||||
2. Optionally, create a Slack Channel (you can use an existing one)
|
||||
|
||||
3. Integrate the created Slack App to your Slack channel:
|
||||
- Click on the channel, go to the Integrations tab, and Add an App.
|
||||

|
||||
|
||||
4. Set the following environment variables that Prowler will read:
|
||||
- `SLACK_API_TOKEN`: the *Slack App OAuth Token* that was previously get.
|
||||
- `SLACK_CHANNEL_ID`: the name of your Slack Channel where Prowler will send the message.
|
||||
@@ -1,16 +1,16 @@
|
||||
# Logging
|
||||
|
||||
Prowler has a logging feature to be as transparent as possible so you can see every action that is going on will the tool is been executing.
|
||||
Prowler has a logging feature to be as transparent as possible, so that you can see every action that is being performed whilst the tool is being executing.
|
||||
|
||||
## Set Log Level
|
||||
## Set Log Level
|
||||
|
||||
There are different log levels depending on the logging information that is desired to be displayed:
|
||||
|
||||
- **DEBUG**: it will show low-level logs of Python.
|
||||
- **INFO**: it will show all the API Calls that are being used in the provider.
|
||||
- **WARNING**: it will show the resources that are being **allowlisted**.
|
||||
- **ERROR**: it will show the errors, e.g., not authorized actions.
|
||||
- **CRITICAL**: default log level, if a critical log appears, it will **exit** Prowler’s execution.
|
||||
- **DEBUG**: It will show low-level logs from Python.
|
||||
- **INFO**: It will show all the API calls that are being invoked by the provider.
|
||||
- **WARNING**: It will show all resources that are being **allowlisted**.
|
||||
- **ERROR**: It will show any errors, e.g., not authorized actions.
|
||||
- **CRITICAL**: The default log level. If a critical log appears, it will **exit** Prowler’s execution.
|
||||
|
||||
You can establish the log level of Prowler with `--log-level` option:
|
||||
|
||||
@@ -20,9 +20,9 @@ prowler <provider> --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
|
||||
|
||||
> By default, Prowler will run with the `CRITICAL` log level, since critical errors will abort the execution.
|
||||
|
||||
## Export Logs to File
|
||||
## Export Logs to File
|
||||
|
||||
Prowler allows you to export the logs in json format with `--log-file` option:
|
||||
Prowler allows you to export the logs in json format with the `--log-file` option:
|
||||
|
||||
```console
|
||||
prowler <provider> --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL} --log-file <file_name>.json
|
||||
@@ -45,4 +45,4 @@ An example of a log file will be the following:
|
||||
"message": "eu-west-2 -- ClientError[124]: An error occurred (UnauthorizedOperation) when calling the DescribeNetworkAcls operation: You are not authorized to perform this operation."
|
||||
}
|
||||
|
||||
> NOTE: Each finding is a `json` object.
|
||||
> NOTE: Each finding is represented as a `json` object.
|
||||
|
||||
@@ -51,15 +51,36 @@ prowler <provider> -e/--excluded-checks ec2 rds
|
||||
```console
|
||||
prowler <provider> -C/--checks-file <checks_list>.json
|
||||
```
|
||||
|
||||
## Severities
|
||||
Each check of Prowler has a severity, there are options related with it:
|
||||
|
||||
- List the available checks in the provider:
|
||||
## Custom Checks
|
||||
Prowler allows you to include your custom checks with the flag:
|
||||
```console
|
||||
prowler <provider> --list-severities
|
||||
prowler <provider> -x/--checks-folder <custom_checks_folder>
|
||||
```
|
||||
- Execute specific severity(s):
|
||||
> S3 URIs are also supported as folders for custom checks, e.g. s3://bucket/prefix/checks_folder/. Make sure that the used credentials have s3:GetObject permissions in the S3 path where the custom checks are located.
|
||||
|
||||
The custom checks folder must contain one subfolder per check, each subfolder must be named as the check and must contain:
|
||||
|
||||
- An empty `__init__.py`: to make Python treat this check folder as a package.
|
||||
- A `check_name.py` containing the check's logic.
|
||||
- A `check_name.metadata.json` containing the check's metadata.
|
||||
>The check name must start with the service name followed by an underscore (e.g., ec2_instance_public_ip).
|
||||
|
||||
To see more information about how to write checks see the [Developer Guide](../developer-guide/checks.md#create-a-new-check-for-a-provider).
|
||||
|
||||
> If you want to run ONLY your custom check(s), import it with -x (--checks-folder) and then run it with -c (--checks), e.g.:
|
||||
```console
|
||||
prowler aws -x s3://bucket/prowler/providers/aws/services/s3/s3_bucket_policy/ -c s3_bucket_policy
|
||||
```
|
||||
|
||||
## Severities
|
||||
Each of Prowler's checks has a severity, which can be:
|
||||
- informational
|
||||
- low
|
||||
- medium
|
||||
- high
|
||||
- critical
|
||||
|
||||
To execute specific severity(s):
|
||||
```console
|
||||
prowler <provider> --severity critical high
|
||||
```
|
||||
|
||||
@@ -6,12 +6,12 @@ Prowler has some checks that analyse pentesting risks (Secrets, Internet Exposed
|
||||
|
||||
Prowler uses `detect-secrets` library to search for any secrets that are stores in plaintext within your environment.
|
||||
|
||||
The actual checks that have this funcionality are:
|
||||
The actual checks that have this functionality are:
|
||||
|
||||
1. autoscaling_find_secrets_ec2_launch_configuration
|
||||
- awslambda_function_no_secrets_in_code
|
||||
- awslambda_function_no_secrets_in_variables
|
||||
- cloudformation_outputs_find_secrets
|
||||
- cloudformation_stack_outputs_find_secrets
|
||||
- ec2_instance_secrets_user_data
|
||||
- ecs_task_definitions_no_environment_secrets
|
||||
- ssm_document_secrets
|
||||
@@ -33,9 +33,8 @@ Several checks analyse resources that are exposed to the Internet, these are:
|
||||
- ec2_instance_internet_facing_with_instance_profile
|
||||
- ec2_instance_public_ip
|
||||
- ec2_networkacl_allow_ingress_any_port
|
||||
- ec2_securitygroup_allow_ingress_from_internet_to_any_port
|
||||
- ec2_securitygroup_allow_wide_open_public_ipv4
|
||||
- ec2_securitygroup_in_use_without_ingress_filtering
|
||||
- ec2_securitygroup_allow_ingress_from_internet_to_any_port
|
||||
- ecr_repositories_not_publicly_accessible
|
||||
- eks_control_plane_endpoint_access_restricted
|
||||
- eks_endpoints_not_publicly_accessible
|
||||
|
||||
@@ -14,4 +14,7 @@ prowler <provider> -i
|
||||
|
||||
- Also, it creates by default a CSV and JSON to see detailed information about the resources extracted.
|
||||
|
||||

|
||||

|
||||
|
||||
## Objections
|
||||
The inventorying process is done with `resourcegroupstaggingapi` calls which means that only resources they have or have had tags will appear (except for the IAM and S3 resources which are done with Boto3 API calls).
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Reporting
|
||||
|
||||
By default, Prowler will generate a CSV, JSON and a HTML report, however you could generate a JSON-ASFF (used by AWS Security Hub) report with `-M` or `--output-modes`:
|
||||
By default, Prowler will generate a CSV, JSON, JSON-OCSF and a HTML report, however you could generate a JSON-ASFF (used by AWS Security Hub) report with `-M` or `--output-modes`:
|
||||
|
||||
```console
|
||||
prowler <provider> -M csv json json-asff html
|
||||
prowler <provider> -M csv json json-ocsf json-asff html
|
||||
```
|
||||
|
||||
## Custom Output Flags
|
||||
@@ -19,21 +19,11 @@ prowler <provider> -M csv json json-asff html -F <custom_report_name>
|
||||
```console
|
||||
prowler <provider> -M csv json json-asff html -o <custom_report_directory>
|
||||
```
|
||||
> Both flags can be used simultainously to provide a custom directory and filename.
|
||||
> Both flags can be used simultaneously to provide a custom directory and filename.
|
||||
```console
|
||||
prowler <provider> -M csv json json-asff html -F <custom_report_name> -o <custom_report_directory>
|
||||
prowler <provider> -M csv json json-asff html \
|
||||
-F <custom_report_name> -o <custom_report_directory>
|
||||
```
|
||||
## Send report to AWS S3 Bucket
|
||||
|
||||
To save your report in an S3 bucket, use `-B`/`--output-bucket` to define a custom output bucket along with `-M` to define the output format that is going to be uploaded to S3:
|
||||
|
||||
```sh
|
||||
prowler <provider> -M csv -B my-bucket/folder/
|
||||
```
|
||||
|
||||
> In the case you do not want to use the assumed role credentials but the initial credentials to put the reports into the S3 bucket, use `-D`/`--output-bucket-no-assume` instead of `-B`/`--output-bucket.
|
||||
|
||||
> Make sure that the used credentials have s3:PutObject permissions in the S3 path where the reports are going to be uploaded.
|
||||
|
||||
## Output Formats
|
||||
|
||||
@@ -41,18 +31,63 @@ Prowler supports natively the following output formats:
|
||||
|
||||
- CSV
|
||||
- JSON
|
||||
- JSON-OCSF
|
||||
- JSON-ASFF
|
||||
- HTML
|
||||
|
||||
Hereunder is the structure for each of the supported report formats by Prowler:
|
||||
|
||||
### HTML
|
||||

|
||||
### CSV
|
||||
| ASSESSMENT_START_TIME | FINDING_UNIQUE_ID | PROVIDER | PROFILE | ACCOUNT_ID | ACCOUNT_NAME | ACCOUNT_EMAIL | ACCOUNT_ARN | ACCOUNT_ORG | ACCOUNT_TAGS | REGION | CHECK_ID | CHECK_TITLE | CHECK_TYPE | STATUS | STATUS_EXTENDED | SERVICE_NAME | SUBSERVICE_NAME | SEVERITY | RESOURCE_ID | RESOURCE_ARN | RESOURCE_TYPE | RESOURCE_DETAILS | RESOURCE_TAGS | DESCRIPTION | RISK | RELATED_URL | REMEDIATION_RECOMMENDATION_TEXT | REMEDIATION_RECOMMENDATION_URL | REMEDIATION_RECOMMENDATION_CODE_NATIVEIAC | REMEDIATION_RECOMMENDATION_CODE_TERRAFORM | REMEDIATION_RECOMMENDATION_CODE_CLI | REMEDIATION_RECOMMENDATION_CODE_OTHER | CATEGORIES | DEPENDS_ON | RELATED_TO | NOTES |
|
||||
| ------- | ----------- | ------ | -------- | ------------ | ----------- | ---------- | ---------- | --------------------- | -------------------------- | -------------- | ----------------- | ------------------------ | --------------- | ---------- | ----------------- | --------- | -------------- | ----------------- | ------------------ | --------------------- | -------------------- | ------------------- | ------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- | -------------------- |
|
||||
|
||||
The following are the columns present in the CSV format:
|
||||
|
||||
- ASSESSMENT_START_TIME
|
||||
- FINDING_UNIQUE_ID
|
||||
- PROVIDER
|
||||
- PROFILE
|
||||
- ACCOUNT_ID
|
||||
- ACCOUNT_NAME
|
||||
- ACCOUNT_EMAIL
|
||||
- ACCOUNT_ARN
|
||||
- ACCOUNT_ORG
|
||||
- ACCOUNT_TAGS
|
||||
- REGION
|
||||
- CHECK_ID
|
||||
- CHECK_TITLE
|
||||
- CHECK_TYPE
|
||||
- STATUS
|
||||
- STATUS_EXTENDED
|
||||
- SERVICE_NAME
|
||||
- SUBSERVICE_NAME
|
||||
- SEVERITY
|
||||
- RESOURCE_ID
|
||||
- RESOURCE_ARN
|
||||
- RESOURCE_TYPE
|
||||
- RESOURCE_DETAILS
|
||||
- RESOURCE_TAGS
|
||||
- DESCRIPTION
|
||||
- COMPLIANCE
|
||||
- RISK
|
||||
- RELATED_URL
|
||||
- REMEDIATION_RECOMMENDATION_TEXT
|
||||
- REMEDIATION_RECOMMENDATION_URL
|
||||
- REMEDIATION_RECOMMENDATION_CODE_NATIVEIAC
|
||||
- REMEDIATION_RECOMMENDATION_CODE_TERRAFORM
|
||||
- REMEDIATION_RECOMMENDATION_CODE_CLI
|
||||
- REMEDIATION_RECOMMENDATION_CODE_OTHER
|
||||
- CATEGORIES
|
||||
- DEPENDS_ON
|
||||
- RELATED_TO
|
||||
- NOTES
|
||||
|
||||
> Since Prowler v3 the CSV column delimiter is the semicolon (`;`)
|
||||
### JSON
|
||||
|
||||
```
|
||||
The following code is an example output of the JSON format:
|
||||
|
||||
```json
|
||||
[{
|
||||
"AssessmentStartTime": "2022-12-01T14:16:57.354413",
|
||||
"FindingUniqueId": "",
|
||||
@@ -71,6 +106,10 @@ Hereunder is the structure for each of the supported report formats by Prowler:
|
||||
"Severity": "low",
|
||||
"ResourceId": "rds-instance-id",
|
||||
"ResourceArn": "",
|
||||
"ResourceTags": {
|
||||
"test": "test",
|
||||
"enironment": "dev"
|
||||
},
|
||||
"ResourceType": "AwsRdsDbInstance",
|
||||
"ResourceDetails": "",
|
||||
"Description": "Ensure RDS instances have minor version upgrade enabled.",
|
||||
@@ -89,8 +128,17 @@ Hereunder is the structure for each of the supported report formats by Prowler:
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Notes": ""
|
||||
},{
|
||||
"Notes": "",
|
||||
"Compliance": {
|
||||
"CIS-1.4": [
|
||||
"1.20"
|
||||
],
|
||||
"CIS-1.5": [
|
||||
"1.20"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"AssessmentStartTime": "2022-12-01T14:16:57.354413",
|
||||
"FindingUniqueId": "",
|
||||
"Provider": "aws",
|
||||
@@ -109,7 +157,7 @@ Hereunder is the structure for each of the supported report formats by Prowler:
|
||||
"ResourceId": "rds-instance-id",
|
||||
"ResourceArn": "",
|
||||
"ResourceType": "AwsRdsDbInstance",
|
||||
"ResourceDetails": "",
|
||||
"ResourceTags": {},
|
||||
"Description": "Ensure RDS instances have minor version upgrade enabled.",
|
||||
"Risk": "Auto Minor Version Upgrade is a feature that you can enable to have your database automatically upgraded when a new minor database engine version is available. Minor version upgrades often patch security vulnerabilities and fix bugs and therefore should be applied.",
|
||||
"RelatedUrl": "https://aws.amazon.com/blogs/database/best-practices-for-upgrading-amazon-rds-to-major-and-minor-versions-of-postgresql/",
|
||||
@@ -126,15 +174,278 @@ Hereunder is the structure for each of the supported report formats by Prowler:
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"Notes": ""
|
||||
"Notes": "",
|
||||
"Compliance": {}
|
||||
}]
|
||||
```
|
||||
|
||||
> NOTE: Each finding is a `json` object within a list. This has changed in v3 since in v2 the format used was [ndjson](http://ndjson.org/).
|
||||
|
||||
|
||||
### JSON-OCSF
|
||||
|
||||
Based on [Open Cybersecurity Schema Framework Security Finding v1.0.0-rc.3](https://schema.ocsf.io/1.0.0-rc.3/classes/security_finding?extensions=)
|
||||
|
||||
```json
|
||||
[{
|
||||
"finding": {
|
||||
"title": "Check if ACM Certificates are about to expire in specific days or less",
|
||||
"desc": "Check if ACM Certificates are about to expire in specific days or less",
|
||||
"supporting_data": {
|
||||
"Risk": "Expired certificates can impact service availability.",
|
||||
"Notes": ""
|
||||
},
|
||||
"remediation": {
|
||||
"kb_articles": [
|
||||
"https://docs.aws.amazon.com/config/latest/developerguide/acm-certificate-expiration-check.html"
|
||||
],
|
||||
"desc": "Monitor certificate expiration and take automated action to renew; replace or remove. Having shorter TTL for any security artifact is a general recommendation; but requires additional automation in place. If not longer required delete certificate. Use AWS config using the managed rule: acm-certificate-expiration-check."
|
||||
},
|
||||
"types": [
|
||||
"Data Protection"
|
||||
],
|
||||
"src_url": "https://docs.aws.amazon.com/config/latest/developerguide/acm-certificate-expiration-check.html",
|
||||
"uid": "prowler-aws-acm_certificates_expiration_check-012345678912-eu-west-1-*.xxxxxxxxxxxxxx",
|
||||
"related_events": []
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"group": {
|
||||
"name": "acm"
|
||||
},
|
||||
"region": "eu-west-1",
|
||||
"name": "xxxxxxxxxxxxxx",
|
||||
"uid": "arn:aws:acm:eu-west-1:012345678912:certificate/xxxxxxxxxxxxxx",
|
||||
"labels": [
|
||||
{
|
||||
"Key": "project",
|
||||
"Value": "prowler-pro"
|
||||
},
|
||||
{
|
||||
"Key": "environment",
|
||||
"Value": "dev"
|
||||
},
|
||||
{
|
||||
"Key": "terraform",
|
||||
"Value": "true"
|
||||
},
|
||||
{
|
||||
"Key": "terraform_state",
|
||||
"Value": "aws"
|
||||
}
|
||||
],
|
||||
"type": "AwsCertificateManagerCertificate",
|
||||
"details": ""
|
||||
}
|
||||
],
|
||||
"status_detail": "ACM Certificate for xxxxxxxxxxxxxx expires in 111 days.",
|
||||
"compliance": {
|
||||
"status": "Success",
|
||||
"requirements": [
|
||||
"CISA: ['your-data-2']",
|
||||
"SOC2: ['cc_6_7']",
|
||||
"MITRE-ATTACK: ['T1040']",
|
||||
"GDPR: ['article_32']",
|
||||
"HIPAA: ['164_308_a_4_ii_a', '164_312_e_1']",
|
||||
"AWS-Well-Architected-Framework-Security-Pillar: ['SEC09-BP01']",
|
||||
"NIST-800-171-Revision-2: ['3_13_1', '3_13_2', '3_13_8', '3_13_11']",
|
||||
"NIST-800-53-Revision-4: ['ac_4', 'ac_17_2', 'sc_12']",
|
||||
"NIST-800-53-Revision-5: ['sc_7_12', 'sc_7_16']",
|
||||
"NIST-CSF-1.1: ['ac_5', 'ds_2']",
|
||||
"RBI-Cyber-Security-Framework: ['annex_i_1_3']",
|
||||
"FFIEC: ['d3-pc-im-b-1']",
|
||||
"FedRamp-Moderate-Revision-4: ['ac-4', 'ac-17-2', 'sc-12']",
|
||||
"FedRAMP-Low-Revision-4: ['ac-17', 'sc-12']"
|
||||
],
|
||||
"status_detail": "ACM Certificate for xxxxxxxxxxxxxx expires in 111 days."
|
||||
},
|
||||
"message": "ACM Certificate for xxxxxxxxxxxxxx expires in 111 days.",
|
||||
"severity_id": 4,
|
||||
"severity": "High",
|
||||
"cloud": {
|
||||
"account": {
|
||||
"name": "",
|
||||
"uid": "012345678912"
|
||||
},
|
||||
"region": "eu-west-1",
|
||||
"org": {
|
||||
"uid": "",
|
||||
"name": ""
|
||||
},
|
||||
"provider": "aws",
|
||||
"project_uid": ""
|
||||
},
|
||||
"time": "2023-06-30 10:28:55.297615",
|
||||
"metadata": {
|
||||
"original_time": "2023-06-30T10:28:55.297615",
|
||||
"profiles": [
|
||||
"dev"
|
||||
],
|
||||
"product": {
|
||||
"language": "en",
|
||||
"name": "Prowler",
|
||||
"version": "3.6.1",
|
||||
"vendor_name": "Prowler/ProwlerPro",
|
||||
"feature": {
|
||||
"name": "acm_certificates_expiration_check",
|
||||
"uid": "acm_certificates_expiration_check",
|
||||
"version": "3.6.1"
|
||||
}
|
||||
},
|
||||
"version": "1.0.0-rc.3"
|
||||
},
|
||||
"state_id": 0,
|
||||
"state": "New",
|
||||
"status_id": 1,
|
||||
"status": "Success",
|
||||
"type_uid": 200101,
|
||||
"type_name": "Security Finding: Create",
|
||||
"impact_id": 0,
|
||||
"impact": "Unknown",
|
||||
"confidence_id": 0,
|
||||
"confidence": "Unknown",
|
||||
"activity_id": 1,
|
||||
"activity_name": "Create",
|
||||
"category_uid": 2,
|
||||
"category_name": "Findings",
|
||||
"class_uid": 2001,
|
||||
"class_name": "Security Finding"
|
||||
},{
|
||||
"finding": {
|
||||
"title": "Check if ACM Certificates are about to expire in specific days or less",
|
||||
"desc": "Check if ACM Certificates are about to expire in specific days or less",
|
||||
"supporting_data": {
|
||||
"Risk": "Expired certificates can impact service availability.",
|
||||
"Notes": ""
|
||||
},
|
||||
"remediation": {
|
||||
"kb_articles": [
|
||||
"https://docs.aws.amazon.com/config/latest/developerguide/acm-certificate-expiration-check.html"
|
||||
],
|
||||
"desc": "Monitor certificate expiration and take automated action to renew; replace or remove. Having shorter TTL for any security artifact is a general recommendation; but requires additional automation in place. If not longer required delete certificate. Use AWS config using the managed rule: acm-certificate-expiration-check."
|
||||
},
|
||||
"types": [
|
||||
"Data Protection"
|
||||
],
|
||||
"src_url": "https://docs.aws.amazon.com/config/latest/developerguide/acm-certificate-expiration-check.html",
|
||||
"uid": "prowler-aws-acm_certificates_expiration_check-012345678912-eu-west-1-xxxxxxxxxxxxx",
|
||||
"related_events": []
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"group": {
|
||||
"name": "acm"
|
||||
},
|
||||
"region": "eu-west-1",
|
||||
"name": "xxxxxxxxxxxxx",
|
||||
"uid": "arn:aws:acm:eu-west-1:012345678912:certificate/3ea965a0-368d-4d13-95eb-5042a994edc4",
|
||||
"labels": [
|
||||
{
|
||||
"Key": "name",
|
||||
"Value": "prowler-pro-saas-dev-acm-internal-wildcard"
|
||||
},
|
||||
{
|
||||
"Key": "project",
|
||||
"Value": "prowler-pro-saas"
|
||||
},
|
||||
{
|
||||
"Key": "environment",
|
||||
"Value": "dev"
|
||||
},
|
||||
{
|
||||
"Key": "terraform",
|
||||
"Value": "true"
|
||||
},
|
||||
{
|
||||
"Key": "terraform_state",
|
||||
"Value": "aws/saas/base"
|
||||
}
|
||||
],
|
||||
"type": "AwsCertificateManagerCertificate",
|
||||
"details": ""
|
||||
}
|
||||
],
|
||||
"status_detail": "ACM Certificate for xxxxxxxxxxxxx expires in 119 days.",
|
||||
"compliance": {
|
||||
"status": "Success",
|
||||
"requirements": [
|
||||
"CISA: ['your-data-2']",
|
||||
"SOC2: ['cc_6_7']",
|
||||
"MITRE-ATTACK: ['T1040']",
|
||||
"GDPR: ['article_32']",
|
||||
"HIPAA: ['164_308_a_4_ii_a', '164_312_e_1']",
|
||||
"AWS-Well-Architected-Framework-Security-Pillar: ['SEC09-BP01']",
|
||||
"NIST-800-171-Revision-2: ['3_13_1', '3_13_2', '3_13_8', '3_13_11']",
|
||||
"NIST-800-53-Revision-4: ['ac_4', 'ac_17_2', 'sc_12']",
|
||||
"NIST-800-53-Revision-5: ['sc_7_12', 'sc_7_16']",
|
||||
"NIST-CSF-1.1: ['ac_5', 'ds_2']",
|
||||
"RBI-Cyber-Security-Framework: ['annex_i_1_3']",
|
||||
"FFIEC: ['d3-pc-im-b-1']",
|
||||
"FedRamp-Moderate-Revision-4: ['ac-4', 'ac-17-2', 'sc-12']",
|
||||
"FedRAMP-Low-Revision-4: ['ac-17', 'sc-12']"
|
||||
],
|
||||
"status_detail": "ACM Certificate for xxxxxxxxxxxxx expires in 119 days."
|
||||
},
|
||||
"message": "ACM Certificate for xxxxxxxxxxxxx expires in 119 days.",
|
||||
"severity_id": 4,
|
||||
"severity": "High",
|
||||
"cloud": {
|
||||
"account": {
|
||||
"name": "",
|
||||
"uid": "012345678912"
|
||||
},
|
||||
"region": "eu-west-1",
|
||||
"org": {
|
||||
"uid": "",
|
||||
"name": ""
|
||||
},
|
||||
"provider": "aws",
|
||||
"project_uid": ""
|
||||
},
|
||||
"time": "2023-06-30 10:28:55.297615",
|
||||
"metadata": {
|
||||
"original_time": "2023-06-30T10:28:55.297615",
|
||||
"profiles": [
|
||||
"dev"
|
||||
],
|
||||
"product": {
|
||||
"language": "en",
|
||||
"name": "Prowler",
|
||||
"version": "3.6.1",
|
||||
"vendor_name": "Prowler/ProwlerPro",
|
||||
"feature": {
|
||||
"name": "acm_certificates_expiration_check",
|
||||
"uid": "acm_certificates_expiration_check",
|
||||
"version": "3.6.1"
|
||||
}
|
||||
},
|
||||
"version": "1.0.0-rc.3"
|
||||
},
|
||||
"state_id": 0,
|
||||
"state": "New",
|
||||
"status_id": 1,
|
||||
"status": "Success",
|
||||
"type_uid": 200101,
|
||||
"type_name": "Security Finding: Create",
|
||||
"impact_id": 0,
|
||||
"impact": "Unknown",
|
||||
"confidence_id": 0,
|
||||
"confidence": "Unknown",
|
||||
"activity_id": 1,
|
||||
"activity_name": "Create",
|
||||
"category_uid": 2,
|
||||
"category_name": "Findings",
|
||||
"class_uid": 2001,
|
||||
"class_name": "Security Finding"
|
||||
}]
|
||||
```
|
||||
|
||||
> NOTE: Each finding is a `json` object.
|
||||
|
||||
### JSON-ASFF
|
||||
|
||||
```
|
||||
The following code is an example output of the [JSON-ASFF](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format-syntax.html) format:
|
||||
|
||||
```json
|
||||
[{
|
||||
"SchemaVersion": "2018-10-08",
|
||||
"Id": "prowler-rds_instance_minor_version_upgrade_enabled-ACCOUNT_ID-eu-west-1-b1ade474a",
|
||||
@@ -166,7 +477,30 @@ Hereunder is the structure for each of the supported report formats by Prowler:
|
||||
],
|
||||
"Compliance": {
|
||||
"Status": "PASSED",
|
||||
"RelatedRequirements": []
|
||||
"RelatedRequirements": [
|
||||
"CISA your-systems-2 booting-up-thing-to-do-first-3",
|
||||
"CIS-1.5 2.3.2",
|
||||
"AWS-Foundational-Security-Best-Practices rds",
|
||||
"RBI-Cyber-Security-Framework annex_i_6",
|
||||
"FFIEC d3-cc-pm-b-1 d3-cc-pm-b-3"
|
||||
],
|
||||
"AssociatedStandards": [
|
||||
{
|
||||
"StandardsId": "CISA"
|
||||
},
|
||||
{
|
||||
"StandardsId": "CIS-1.5"
|
||||
},
|
||||
{
|
||||
"StandardsId": "AWS-Foundational-Security-Best-Practices"
|
||||
},
|
||||
{
|
||||
"StandardsId": "RBI-Cyber-Security-Framework"
|
||||
},
|
||||
{
|
||||
"StandardsId": "FFIEC"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Remediation": {
|
||||
"Recommendation": {
|
||||
@@ -205,7 +539,30 @@ Hereunder is the structure for each of the supported report formats by Prowler:
|
||||
],
|
||||
"Compliance": {
|
||||
"Status": "PASSED",
|
||||
"RelatedRequirements": []
|
||||
"RelatedRequirements": [
|
||||
"CISA your-systems-2 booting-up-thing-to-do-first-3",
|
||||
"CIS-1.5 2.3.2",
|
||||
"AWS-Foundational-Security-Best-Practices rds",
|
||||
"RBI-Cyber-Security-Framework annex_i_6",
|
||||
"FFIEC d3-cc-pm-b-1 d3-cc-pm-b-3"
|
||||
],
|
||||
"AssociatedStandards": [
|
||||
{
|
||||
"StandardsId": "CISA"
|
||||
},
|
||||
{
|
||||
"StandardsId": "CIS-1.5"
|
||||
},
|
||||
{
|
||||
"StandardsId": "AWS-Foundational-Security-Best-Practices"
|
||||
},
|
||||
{
|
||||
"StandardsId": "RBI-Cyber-Security-Framework"
|
||||
},
|
||||
{
|
||||
"StandardsId": "FFIEC"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Remediation": {
|
||||
"Recommendation": {
|
||||
@@ -216,4 +573,4 @@ Hereunder is the structure for each of the supported report formats by Prowler:
|
||||
}]
|
||||
```
|
||||
|
||||
> NOTE: Each finding is a `json` object.
|
||||
> NOTE: Each finding is a `json` object within a list.
|
||||
|
||||
66
mkdocs.yml
@@ -9,7 +9,7 @@ theme:
|
||||
language: en
|
||||
logo: img/prowler-logo.png
|
||||
name: material
|
||||
favicon: img/ProwlerPro-icon.svg
|
||||
favicon: img/prowler-icon.svg
|
||||
features:
|
||||
- navigation.tabs
|
||||
- navigation.tabs.sticky
|
||||
@@ -25,31 +25,55 @@ repo_url: https://github.com/prowler-cloud/prowler/
|
||||
repo_name: prowler-cloud/prowler
|
||||
|
||||
nav:
|
||||
- Getting Started:
|
||||
- Overview: index.md
|
||||
- Requirements: getting-started/requirements.md
|
||||
- Tutorials:
|
||||
- Miscellaneous: tutorials/misc.md
|
||||
- Reporting: tutorials/reporting.md
|
||||
- Compliance: tutorials/compliance.md
|
||||
- Quick Inventory: tutorials/quick-inventory.md
|
||||
- Configuration File: tutorials/configuration_file.md
|
||||
- Logging: tutorials/logging.md
|
||||
- Allowlist: tutorials/allowlist.md
|
||||
- Pentesting: tutorials/pentesting.md
|
||||
- AWS:
|
||||
- Getting Started:
|
||||
- Overview: index.md
|
||||
- Requirements: getting-started/requirements.md
|
||||
- Tutorials:
|
||||
- Miscellaneous: tutorials/misc.md
|
||||
- Reporting: tutorials/reporting.md
|
||||
- Compliance: tutorials/compliance.md
|
||||
- Quick Inventory: tutorials/quick-inventory.md
|
||||
- Slack Integration: tutorials/integrations.md
|
||||
- Configuration File: tutorials/configuration_file.md
|
||||
- Logging: tutorials/logging.md
|
||||
- Allowlist: tutorials/allowlist.md
|
||||
- Pentesting: tutorials/pentesting.md
|
||||
- Developer Guide: developer-guide/introduction.md
|
||||
- AWS:
|
||||
- Authentication: tutorials/aws/authentication.md
|
||||
- Assume Role: tutorials/aws/role-assumption.md
|
||||
- AWS Security Hub: tutorials/aws/securityhub.md
|
||||
- AWS Organizations: tutorials/aws/organizations.md
|
||||
- AWS Regions and Partitions: tutorials/aws/regions-and-partitions.md
|
||||
- Scan Multiple AWS Accounts: tutorials/aws/multiaccount.md
|
||||
- Send reports to AWS S3: tutorials/aws/s3.md
|
||||
- AWS CloudShell: tutorials/aws/cloudshell.md
|
||||
- Azure:
|
||||
- Checks v2 to v3 Mapping: tutorials/aws/v2_to_v3_checks_mapping.md
|
||||
- Tag-based Scan: tutorials/aws/tag-based-scan.md
|
||||
- Resource ARNs based Scan: tutorials/aws/resource-arn-based-scan.md
|
||||
- Boto3 Configuration: tutorials/aws/boto3-configuration.md
|
||||
- Azure:
|
||||
- Authentication: tutorials/azure/authentication.md
|
||||
- Subscriptions: tutorials/azure/subscriptions.md
|
||||
- Contact Us: contact.md
|
||||
- Troubleshooting: troubleshooting.md
|
||||
- About: about.md
|
||||
- ProwlerPro: https://prowler.pro
|
||||
- Google Cloud:
|
||||
- Authentication: tutorials/gcp/authentication.md
|
||||
- Developer Guide:
|
||||
- Introduction: developer-guide/introduction.md
|
||||
- Audit Info: developer-guide/audit-info.md
|
||||
- Services: developer-guide/services.md
|
||||
- Checks: developer-guide/checks.md
|
||||
- Documentation: developer-guide/documentation.md
|
||||
- Compliance: developer-guide/security-compliance-framework.md
|
||||
- Outputs: developer-guide/outputs.md
|
||||
- Integrations: developer-guide/integrations.md
|
||||
- Testing:
|
||||
- Unit Tests: developer-guide/unit-testing.md
|
||||
- Integration Tests: developer-guide/integration-testing.md
|
||||
- Security: security.md
|
||||
- Contact Us: contact.md
|
||||
- Troubleshooting: troubleshooting.md
|
||||
- About: about.md
|
||||
- ProwlerPro: https://prowler.pro
|
||||
# Customization
|
||||
extra:
|
||||
consent:
|
||||
@@ -73,7 +97,7 @@ extra:
|
||||
link: https://twitter.com/prowlercloud
|
||||
|
||||
# Copyright
|
||||
copyright: Copyright © 2022 Toni de la Fuente, Maintained by the Prowler Team at Verica, Inc.</a>.
|
||||
copyright: Copyright © 2022 Toni de la Fuente, Maintained by the Prowler Team at Verica, Inc.</a>
|
||||
|
||||
markdown_extensions:
|
||||
- abbr
|
||||
@@ -112,4 +136,4 @@ markdown_extensions:
|
||||
alternate_style: true
|
||||
- pymdownx.tasklist:
|
||||
custom_checkbox: true
|
||||
- pymdownx.tilde
|
||||
- pymdownx.tilde
|
||||
|
||||
@@ -4,7 +4,7 @@ AWSTemplateFormatVersion: '2010-09-09'
|
||||
# aws cloudformation create-stack \
|
||||
# --capabilities CAPABILITY_IAM --capabilities CAPABILITY_NAMED_IAM \
|
||||
# --template-body "file://create_role_to_assume_cfn.yaml" \
|
||||
# --stack-name "ProwlerExecRole" \
|
||||
# --stack-name "ProwlerScanRole" \
|
||||
# --parameters "ParameterKey=AuthorisedARN,ParameterValue=arn:aws:iam::123456789012:root"
|
||||
#
|
||||
Description: |
|
||||
@@ -13,7 +13,7 @@ Description: |
|
||||
account to assume that role. The role name and the ARN of the trusted user can all be passed
|
||||
to the CloudFormation stack as parameters. Then you can run Prowler to perform a security
|
||||
assessment with a command like:
|
||||
./prowler -A <THIS_ACCOUNT_ID> -R ProwlerExecRole
|
||||
prowler --role ProwlerScanRole.ARN
|
||||
Parameters:
|
||||
AuthorisedARN:
|
||||
Description: |
|
||||
@@ -22,12 +22,12 @@ Parameters:
|
||||
Type: String
|
||||
ProwlerRoleName:
|
||||
Description: |
|
||||
Name of the IAM role that will have these policies attached. Default: ProwlerExecRole
|
||||
Name of the IAM role that will have these policies attached. Default: ProwlerScanRole
|
||||
Type: String
|
||||
Default: 'ProwlerExecRole'
|
||||
Default: 'ProwlerScanRole'
|
||||
|
||||
Resources:
|
||||
ProwlerExecRole:
|
||||
ProwlerScanRole:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
AssumeRolePolicyDocument:
|
||||
@@ -42,31 +42,49 @@ Resources:
|
||||
# Bool:
|
||||
# 'aws:MultiFactorAuthPresent': true
|
||||
# This is 12h that is maximum allowed, Minimum is 3600 = 1h
|
||||
# to take advantage of this use -T like in './prowler -A <ACCOUNT_ID_TO_ASSUME> -R ProwlerExecRole -T 43200 -M text,html'
|
||||
# to take advantage of this use -T like in './prowler --role ProwlerScanRole.ARN -T 43200'
|
||||
MaxSessionDuration: 43200
|
||||
ManagedPolicyArns:
|
||||
- 'arn:aws:iam::aws:policy/SecurityAudit'
|
||||
- 'arn:aws:iam::aws:policy/job-function/ViewOnlyAccess'
|
||||
RoleName: !Sub ${ProwlerRoleName}
|
||||
Policies:
|
||||
- PolicyName: ProwlerExecRoleAdditionalViewPrivileges
|
||||
- PolicyName: ProwlerScanRoleAdditionalViewPrivileges
|
||||
PolicyDocument:
|
||||
Version : '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- 'ds:ListAuthorizedApplications'
|
||||
- 'account:Get*'
|
||||
- 'appstream:Describe*'
|
||||
- 'appstream:List*'
|
||||
- 'codeartifact:List*'
|
||||
- 'codebuild:BatchGet*'
|
||||
- 'ds:Get*'
|
||||
- 'ds:Describe*'
|
||||
- 'ds:List*'
|
||||
- 'ec2:GetEbsEncryptionByDefault'
|
||||
- 'ecr:Describe*'
|
||||
- 'elasticfilesystem:DescribeBackupPolicy'
|
||||
- 'glue:GetConnections'
|
||||
- 'glue:GetSecurityConfiguration'
|
||||
- 'glue:GetSecurityConfiguration*'
|
||||
- 'glue:SearchTables'
|
||||
- 'lambda:GetFunction'
|
||||
- 'lambda:GetFunction*'
|
||||
- 'macie2:GetMacieSession'
|
||||
- 's3:GetAccountPublicAccessBlock'
|
||||
- 'shield:DescribeProtection'
|
||||
- 'shield:GetSubscriptionState'
|
||||
- 'securityhub:BatchImportFindings'
|
||||
- 'securityhub:GetFindings'
|
||||
- 'ssm:GetDocument'
|
||||
- 'support:Describe*'
|
||||
- 'tag:GetTagKeys'
|
||||
Resource: '*'
|
||||
- PolicyName: ProwlerScanRoleAdditionalViewPrivilegesApiGateway
|
||||
PolicyDocument:
|
||||
Version : '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- 'apigateway:GET'
|
||||
Resource: 'arn:aws:apigateway:*::/restapis/*'
|
||||
|
||||
@@ -3,24 +3,51 @@
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"ds:ListAuthorizedApplications",
|
||||
"account:Get*",
|
||||
"appstream:Describe*",
|
||||
"appstream:List*",
|
||||
"backup:List*",
|
||||
"cloudtrail:GetInsightSelectors",
|
||||
"codeartifact:List*",
|
||||
"codebuild:BatchGet*",
|
||||
"drs:Describe*",
|
||||
"ds:Get*",
|
||||
"ds:Describe*",
|
||||
"ds:List*",
|
||||
"ec2:GetEbsEncryptionByDefault",
|
||||
"ecr:Describe*",
|
||||
"ecr:GetRegistryScanningConfiguration",
|
||||
"elasticfilesystem:DescribeBackupPolicy",
|
||||
"glue:GetConnections",
|
||||
"glue:GetSecurityConfiguration",
|
||||
"glue:GetSecurityConfiguration*",
|
||||
"glue:SearchTables",
|
||||
"lambda:GetFunction",
|
||||
"lambda:GetFunction*",
|
||||
"logs:FilterLogEvents",
|
||||
"macie2:GetMacieSession",
|
||||
"s3:GetAccountPublicAccessBlock",
|
||||
"shield:DescribeProtection",
|
||||
"shield:GetSubscriptionState",
|
||||
"securityhub:BatchImportFindings",
|
||||
"securityhub:GetFindings",
|
||||
"ssm:GetDocument",
|
||||
"ssm-incidents:List*",
|
||||
"support:Describe*",
|
||||
"tag:GetTagKeys"
|
||||
"tag:GetTagKeys",
|
||||
"wellarchitected:List*"
|
||||
],
|
||||
"Resource": "*",
|
||||
"Effect": "Allow",
|
||||
"Sid": "AllowMoreReadForProwler"
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"apigateway:GET"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:apigateway:*::/restapis/*",
|
||||
"arn:aws:apigateway:*::/apis/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
3166
poetry.lock
generated
Normal file
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from prowler.lib.banner import print_banner
|
||||
@@ -11,32 +12,37 @@ from prowler.lib.check.check import (
|
||||
exclude_services_to_run,
|
||||
execute_checks,
|
||||
list_categories,
|
||||
list_checks_json,
|
||||
list_services,
|
||||
parse_checks_from_folder,
|
||||
print_categories,
|
||||
print_checks,
|
||||
print_compliance_frameworks,
|
||||
print_compliance_requirements,
|
||||
print_services,
|
||||
remove_custom_checks_module,
|
||||
)
|
||||
from prowler.lib.check.checks_loader import load_checks_to_execute
|
||||
from prowler.lib.check.compliance import update_checks_metadata_with_compliance
|
||||
from prowler.lib.cli.parser import ProwlerArgumentParser
|
||||
from prowler.lib.logger import logger, set_logging_config
|
||||
from prowler.lib.outputs.outputs import (
|
||||
extract_findings_statistics,
|
||||
send_to_s3_bucket,
|
||||
)
|
||||
from prowler.lib.outputs.compliance import display_compliance_table
|
||||
from prowler.lib.outputs.html import add_html_footer, fill_html_overview_statistics
|
||||
from prowler.lib.outputs.json import close_json
|
||||
from prowler.lib.outputs.outputs import extract_findings_statistics
|
||||
from prowler.lib.outputs.slack import send_slack_message
|
||||
from prowler.lib.outputs.summary_table import display_summary_table
|
||||
from prowler.providers.aws.lib.allowlist.allowlist import parse_allowlist_file
|
||||
from prowler.providers.aws.lib.quick_inventory.quick_inventory import quick_inventory
|
||||
from prowler.providers.aws.lib.s3.s3 import send_to_s3_bucket
|
||||
from prowler.providers.aws.lib.security_hub.security_hub import (
|
||||
resolve_security_hub_previous_findings,
|
||||
)
|
||||
from prowler.providers.common.audit_info import set_provider_audit_info
|
||||
from prowler.providers.common.allowlist import set_provider_allowlist
|
||||
from prowler.providers.common.audit_info import (
|
||||
set_provider_audit_info,
|
||||
set_provider_execution_parameters,
|
||||
)
|
||||
from prowler.providers.common.outputs import set_provider_output_options
|
||||
from prowler.providers.common.quick_inventory import run_provider_quick_inventory
|
||||
|
||||
|
||||
def prowler():
|
||||
@@ -52,18 +58,19 @@ def prowler():
|
||||
services = args.services
|
||||
categories = args.categories
|
||||
checks_file = args.checks_file
|
||||
checks_folder = args.checks_folder
|
||||
severities = args.severity
|
||||
compliance_framework = args.compliance
|
||||
|
||||
if not args.no_banner:
|
||||
print_banner(args)
|
||||
|
||||
# We treat the compliance framework as another output format
|
||||
if compliance_framework:
|
||||
args.output_modes.extend(compliance_framework)
|
||||
|
||||
# Set Logger configuration
|
||||
set_logging_config(args.log_file, args.log_level)
|
||||
|
||||
if args.no_banner:
|
||||
print_banner(args)
|
||||
set_logging_config(args.log_level, args.log_file, args.only_logs)
|
||||
|
||||
if args.list_services:
|
||||
print_services(list_services(provider))
|
||||
@@ -74,33 +81,26 @@ def prowler():
|
||||
bulk_checks_metadata = bulk_load_checks_metadata(provider)
|
||||
|
||||
if args.list_categories:
|
||||
print_categories(list_categories(provider, bulk_checks_metadata))
|
||||
print_categories(list_categories(bulk_checks_metadata))
|
||||
sys.exit()
|
||||
|
||||
bulk_compliance_frameworks = {}
|
||||
# Load compliance frameworks
|
||||
logger.debug("Loading compliance frameworks from .json files")
|
||||
|
||||
# Load the compliance framework if specified with --compliance
|
||||
# If some compliance argument is specified we have to load it
|
||||
if (
|
||||
args.list_compliance
|
||||
or args.list_compliance_requirements
|
||||
or compliance_framework
|
||||
):
|
||||
bulk_compliance_frameworks = bulk_load_compliance_frameworks(provider)
|
||||
# Complete checks metadata with the compliance framework specification
|
||||
update_checks_metadata_with_compliance(
|
||||
bulk_compliance_frameworks, bulk_checks_metadata
|
||||
bulk_compliance_frameworks = bulk_load_compliance_frameworks(provider)
|
||||
# Complete checks metadata with the compliance framework specification
|
||||
update_checks_metadata_with_compliance(
|
||||
bulk_compliance_frameworks, bulk_checks_metadata
|
||||
)
|
||||
if args.list_compliance:
|
||||
print_compliance_frameworks(bulk_compliance_frameworks)
|
||||
sys.exit()
|
||||
if args.list_compliance_requirements:
|
||||
print_compliance_requirements(
|
||||
bulk_compliance_frameworks, args.list_compliance_requirements
|
||||
)
|
||||
if args.list_compliance:
|
||||
print_compliance_frameworks(bulk_compliance_frameworks)
|
||||
sys.exit()
|
||||
if args.list_compliance_requirements:
|
||||
print_compliance_requirements(
|
||||
bulk_compliance_frameworks, args.list_compliance_requirements
|
||||
)
|
||||
sys.exit()
|
||||
sys.exit()
|
||||
|
||||
# Load checks to execute
|
||||
checks_to_execute = load_checks_to_execute(
|
||||
@@ -115,41 +115,53 @@ def prowler():
|
||||
provider,
|
||||
)
|
||||
|
||||
# Exclude checks if -e/--excluded-checks
|
||||
if excluded_checks:
|
||||
checks_to_execute = exclude_checks_to_run(checks_to_execute, excluded_checks)
|
||||
|
||||
# Exclude services if -s/--excluded-services
|
||||
if excluded_services:
|
||||
checks_to_execute = exclude_services_to_run(
|
||||
checks_to_execute, excluded_services, provider
|
||||
)
|
||||
|
||||
# Sort final check list
|
||||
checks_to_execute = sorted(checks_to_execute)
|
||||
# if --list-checks-json, dump a json file and exit
|
||||
if args.list_checks_json:
|
||||
print(list_checks_json(provider, sorted(checks_to_execute)))
|
||||
sys.exit()
|
||||
|
||||
# If -l/--list-checks passed as argument, print checks to execute and quit
|
||||
if args.list_checks:
|
||||
print_checks(provider, checks_to_execute, bulk_checks_metadata)
|
||||
print_checks(provider, sorted(checks_to_execute), bulk_checks_metadata)
|
||||
sys.exit()
|
||||
|
||||
# Set the audit info based on the selected provider
|
||||
audit_info = set_provider_audit_info(provider, args.__dict__)
|
||||
|
||||
# Parse content from Allowlist file and get it, if necessary, from S3
|
||||
if provider == "aws" and args.allowlist_file:
|
||||
allowlist_file = parse_allowlist_file(audit_info, args.allowlist_file)
|
||||
else:
|
||||
allowlist_file = None
|
||||
# Import custom checks from folder
|
||||
if checks_folder:
|
||||
parse_checks_from_folder(audit_info, checks_folder, provider)
|
||||
|
||||
# Setting output options based on the selected provider
|
||||
# Exclude checks if -e/--excluded-checks
|
||||
if excluded_checks:
|
||||
checks_to_execute = exclude_checks_to_run(checks_to_execute, excluded_checks)
|
||||
|
||||
# Exclude services if --excluded-services
|
||||
if excluded_services:
|
||||
checks_to_execute = exclude_services_to_run(
|
||||
checks_to_execute, excluded_services, provider
|
||||
)
|
||||
|
||||
# Once the audit_info is set and we have the eventual checks based on the resource identifier,
|
||||
# it is time to check what Prowler's checks are going to be executed
|
||||
if audit_info.audit_resources:
|
||||
checks_from_resources = set_provider_execution_parameters(provider, audit_info)
|
||||
checks_to_execute = checks_to_execute.intersection(checks_from_resources)
|
||||
|
||||
# Sort final check list
|
||||
checks_to_execute = sorted(checks_to_execute)
|
||||
|
||||
# Parse Allowlist
|
||||
allowlist_file = set_provider_allowlist(provider, audit_info, args)
|
||||
|
||||
# Set output options based on the selected provider
|
||||
audit_output_options = set_provider_output_options(
|
||||
provider, args, audit_info, allowlist_file, bulk_checks_metadata
|
||||
)
|
||||
|
||||
# Quick Inventory for AWS
|
||||
if provider == "aws" and args.quick_inventory:
|
||||
quick_inventory(audit_info, args.output_directory)
|
||||
# Run the quick inventory for the provider if available
|
||||
if hasattr(args, "quick_inventory") and args.quick_inventory:
|
||||
run_provider_quick_inventory(provider, audit_info, args)
|
||||
sys.exit()
|
||||
|
||||
# Execute checks
|
||||
@@ -166,10 +178,25 @@ def prowler():
|
||||
# Extract findings stats
|
||||
stats = extract_findings_statistics(findings)
|
||||
|
||||
if args.slack:
|
||||
if "SLACK_API_TOKEN" in os.environ and "SLACK_CHANNEL_ID" in os.environ:
|
||||
_ = send_slack_message(
|
||||
os.environ["SLACK_API_TOKEN"],
|
||||
os.environ["SLACK_CHANNEL_ID"],
|
||||
stats,
|
||||
provider,
|
||||
audit_info,
|
||||
)
|
||||
else:
|
||||
logger.critical(
|
||||
"Slack integration needs SLACK_API_TOKEN and SLACK_CHANNEL_ID environment variables (see more in https://docs.prowler.cloud/en/latest/tutorials/integrations/#slack)."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
if args.output_modes:
|
||||
for mode in args.output_modes:
|
||||
# Close json file if exists
|
||||
if mode == "json" or mode == "json-asff":
|
||||
if "json" in mode:
|
||||
close_json(
|
||||
audit_output_options.output_filename, args.output_directory, mode
|
||||
)
|
||||
@@ -199,27 +226,41 @@ def prowler():
|
||||
)
|
||||
|
||||
# Resolve previous fails of Security Hub
|
||||
if provider == "aws" and args.security_hub:
|
||||
resolve_security_hub_previous_findings(args.output_directory, audit_info)
|
||||
if provider == "aws" and args.security_hub and not args.skip_sh_update:
|
||||
resolve_security_hub_previous_findings(
|
||||
audit_output_options.output_directory,
|
||||
audit_output_options.output_filename,
|
||||
audit_info,
|
||||
)
|
||||
|
||||
# Display summary table
|
||||
display_summary_table(
|
||||
findings,
|
||||
audit_info,
|
||||
audit_output_options,
|
||||
provider,
|
||||
)
|
||||
|
||||
if compliance_framework and findings:
|
||||
# Display compliance table
|
||||
display_compliance_table(
|
||||
if not args.only_logs:
|
||||
display_summary_table(
|
||||
findings,
|
||||
bulk_checks_metadata,
|
||||
compliance_framework,
|
||||
audit_output_options.output_filename,
|
||||
audit_output_options.output_directory,
|
||||
audit_info,
|
||||
audit_output_options,
|
||||
provider,
|
||||
)
|
||||
|
||||
if compliance_framework and findings:
|
||||
for compliance in compliance_framework:
|
||||
# Display compliance table
|
||||
display_compliance_table(
|
||||
findings,
|
||||
bulk_checks_metadata,
|
||||
compliance,
|
||||
audit_output_options.output_filename,
|
||||
audit_output_options.output_directory,
|
||||
)
|
||||
|
||||
# If custom checks were passed, remove the modules
|
||||
if checks_folder:
|
||||
remove_custom_checks_module(checks_folder, provider)
|
||||
|
||||
# If there are failed findings exit code 3, except if -z is input
|
||||
if not args.ignore_exit_code_3 and stats["total_fail"] > 0:
|
||||
sys.exit(3)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
prowler()
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
{
|
||||
"Framework": "AWS-Audit-Manager-Control-Tower-Guardrails",
|
||||
"Version": "",
|
||||
"Provider": "AWS",
|
||||
"Description": "AWS Control Tower is a management and governance service that you can use to navigate through the setup process and governance requirements that are involved in creating a multi-account AWS environment.",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "1.0.1",
|
||||
"Name": "Disallow launch of EC2 instance types that are not EBS-optimized",
|
||||
"Description": "Checks whether EBS optimization is enabled for your EC2 instances that can be EBS-optimized",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "1.0.1",
|
||||
"Section": "EBS checks",
|
||||
"Service": "ebs"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "1.0.2",
|
||||
"Name": "Disallow EBS volumes that are unattached to an EC2 instance",
|
||||
"Description": "Checks whether EBS volumes are attached to EC2 instances",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "1.0.2",
|
||||
"Section": "EBS checks",
|
||||
"Service": "ebs"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "1.0.3",
|
||||
"Name": "Enable encryption for EBS volumes attached to EC2 instances",
|
||||
"Description": "Checks whether EBS volumes that are in an attached state are encrypted",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "1.0.3",
|
||||
"Section": "EBS checks",
|
||||
"Service": "ebs"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_ebs_default_encryption"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "2.0.1",
|
||||
"Name": "Disallow internet connection through RDP",
|
||||
"Description": "Checks whether security groups that are in use disallow unrestricted incoming TCP traffic to the specified",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "2.0.1",
|
||||
"Section": "Disallow Internet Connection",
|
||||
"Service": "vpc"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "2.0.2",
|
||||
"Name": "Disallow internet connection through SSH",
|
||||
"Description": "Checks whether security groups that are in use disallow unrestricted incoming SSH traffic.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "2.0.2",
|
||||
"Section": "Disallow Internet Connection",
|
||||
"Service": "vpc"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "3.0.1",
|
||||
"Name": "Disallow access to IAM users without MFA",
|
||||
"Description": "Checks whether the AWS Identity and Access Management users have multi-factor authentication (MFA) enabled.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "3.0.1",
|
||||
"Section": "Multi-Factor Authentication",
|
||||
"Service": "iam"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_user_mfa_enabled_console_access"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "3.0.2",
|
||||
"Name": "Disallow console access to IAM users without MFA",
|
||||
"Description": "Checks whether AWS Multi-Factor Authentication (MFA) is enabled for all AWS Identity and Access Management (IAM) users that use a console password.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "3.0.2",
|
||||
"Section": "Multi-Factor Authentication",
|
||||
"Service": "iam"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_user_mfa_enabled_console_access"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "3.0.3",
|
||||
"Name": "Enable MFA for the root user",
|
||||
"Description": "Checks whether the root user of your AWS account requires multi-factor authentication for console sign-in.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "3.0.3",
|
||||
"Section": "Multi-Factor Authentication",
|
||||
"Service": "iam"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_root_mfa_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "4.0.1",
|
||||
"Name": "Disallow public access to RDS database instances",
|
||||
"Description": "Checks whether the Amazon Relational Database Service (RDS) instances are not publicly accessible. The rule is non-compliant if the publiclyAccessible field is true in the instance configuration item.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "4.0.1",
|
||||
"Section": "Disallow Public Access",
|
||||
"Service": "rds"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_no_public_access"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "4.0.2",
|
||||
"Name": "Disallow public access to RDS database snapshots",
|
||||
"Description": "Checks if Amazon Relational Database Service (Amazon RDS) snapshots are public. The rule is non-compliant if any existing and new Amazon RDS snapshots are public.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "4.0.2",
|
||||
"Section": "Disallow Public Access",
|
||||
"Service": "rds"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_snapshots_public_access"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "4.1.1",
|
||||
"Name": "Disallow public read access to S3 buckets",
|
||||
"Description": "Checks that your S3 buckets do not allow public read access.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "4.1.1",
|
||||
"Section": "Disallow Public Access",
|
||||
"Service": "s3"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_no_public_access"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "4.1.2",
|
||||
"Name": "Disallow public write access to S3 buckets",
|
||||
"Description": "Checks that your S3 buckets do not allow public write access.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "4.1.2",
|
||||
"Section": "Disallow Public Access",
|
||||
"Service": "s3"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"s3_bucket_policy_public_write_access"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "5.0.1",
|
||||
"Name": "Disallow RDS database instances that are not storage encrypted ",
|
||||
"Description": "Checks whether storage encryption is enabled for your RDS DB instances.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "5.0.1",
|
||||
"Section": "Disallow Instances",
|
||||
"Service": "rds"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_storage_encrypted"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "5.1.1",
|
||||
"Name": "Disallow S3 buckets that are not versioning enabled",
|
||||
"Description": "Checks whether versioning is enabled for your S3 buckets.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "5.1.1",
|
||||
"Section": "Disallow Instances",
|
||||
"Service": "s3"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"s3_bucket_object_versioning"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,605 @@
|
||||
{
|
||||
"Framework": "AWS-Foundational-Security-Best-Practices",
|
||||
"Version": "",
|
||||
"Provider": "AWS",
|
||||
"Description": "The AWS Foundational Security Best Practices standard is a set of controls that detect when your deployed accounts and resources deviate from security best practices.",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "account",
|
||||
"Name": "Account",
|
||||
"Description": "This section contains recommendations for configuring AWS Account.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "account",
|
||||
"Section": "Account",
|
||||
"Service": "account"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"account_security_contact_information_is_registered"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "acm",
|
||||
"Name": "ACM",
|
||||
"Description": "This section contains recommendations for configuring ACM resources.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "acm",
|
||||
"Section": "Acm",
|
||||
"Service": "acm"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"account_security_contact_information_is_registered"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "api-gateway",
|
||||
"Name": "API Gateway",
|
||||
"Description": "This section contains recommendations for configuring API Gateway resources.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "api-gateway",
|
||||
"Section": "API Gateway",
|
||||
"Service": "apigateway"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"apigateway_client_certificate_enabled",
|
||||
"apigateway_waf_acl_attached",
|
||||
"apigatewayv2_authorizers_enabled",
|
||||
"apigatewayv2_access_logging_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "auto-scaling",
|
||||
"Name": "Benchmark: Auto Scaling",
|
||||
"Description": "This section contains recommendations for configuring Auto Scaling resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "auto-scaling",
|
||||
"Section": "Auto Scaling",
|
||||
"Service": "autoscaling"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "cloudformation",
|
||||
"Name": "Benchmark: CloudFormation",
|
||||
"Description": "This section contains recommendations for configuring CloudFormation resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "cloudformation",
|
||||
"Section": "CloudFormation",
|
||||
"Service": "cloudformation"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "cloudfront",
|
||||
"Name": "Benchmark: CloudFront",
|
||||
"Description": "This section contains recommendations for configuring CloudFront resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "cloudfront",
|
||||
"Section": "CloudFront",
|
||||
"Service": "cloudfront"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudfront_distributions_https_enabled",
|
||||
"cloudfront_distributions_logging_enabled",
|
||||
"cloudfront_distributions_using_waf",
|
||||
"cloudfront_distributions_field_level_encryption_enabled",
|
||||
"cloudfront_distributions_using_deprecated_ssl_protocols"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "cloudtrail",
|
||||
"Name": "Benchmark: CloudTrail",
|
||||
"Description": "This section contains recommendations for configuring CloudTrail resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "cloudtrail",
|
||||
"Section": "CloudTrail",
|
||||
"Service": "cloudtrail"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_kms_encryption_enabled",
|
||||
"cloudtrail_log_file_validation_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "codebuild",
|
||||
"Name": "Benchmark: CodeBuild",
|
||||
"Description": "This section contains recommendations for configuring CodeBuild resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "codebuild",
|
||||
"Section": "CodeBuild",
|
||||
"Service": "codebuild"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "config",
|
||||
"Name": "Benchmark: Config",
|
||||
"Description": "This section contains recommendations for configuring AWS Config.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "config",
|
||||
"Section": "Config",
|
||||
"Service": "config"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"config_recorder_all_regions_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "dms",
|
||||
"Name": "Benchmark: DMS",
|
||||
"Description": "This section contains recommendations for configuring AWS DMS resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "dms",
|
||||
"Section": "DMS",
|
||||
"Service": "dms"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "dynamodb",
|
||||
"Name": "Benchmark: DynamoDB",
|
||||
"Description": "This section contains recommendations for configuring AWS Dynamo DB resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "dynamodb",
|
||||
"Section": "DynamoDB",
|
||||
"Service": "dynamodb"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"dynamodb_accelerator_cluster_encryption_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "ec2",
|
||||
"Name": "Benchmark: EC2",
|
||||
"Description": "This section contains recommendations for configuring EC2 resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ec2",
|
||||
"Section": "EC2",
|
||||
"Service": "ec2"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"ec2_ebs_volume_encryption",
|
||||
"ec2_instance_older_than_specific_days",
|
||||
"vpc_flow_logs_enabled",
|
||||
"ec2_ebs_default_encryption",
|
||||
"ec2_instance_imdsv2_enabled",
|
||||
"ec2_instance_public_ip",
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_not_used"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "ecr",
|
||||
"Name": "Benchmark: Elastic Container Registry",
|
||||
"Description": "This section contains recommendations for configuring AWS ECR resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ecr",
|
||||
"Section": "ECR",
|
||||
"Service": "ecr"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ecr_repositories_scan_images_on_push_enabled",
|
||||
"ecr_repositories_lifecycle_policy_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "ecs",
|
||||
"Name": "Benchmark: Elastic Container Service",
|
||||
"Description": "This section contains recommendations for configuring ECS resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ecs",
|
||||
"Section": "ECS",
|
||||
"Service": "ecs"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ecs_task_definitions_no_environment_secrets"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "efs",
|
||||
"Name": "Benchmark: EFS",
|
||||
"Description": "This section contains recommendations for configuring AWS EFS resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "efs",
|
||||
"Section": "EFS",
|
||||
"Service": "efs"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"efs_encryption_at_rest_enabled",
|
||||
"efs_have_backup_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "eks",
|
||||
"Name": "Benchmark: EKS",
|
||||
"Description": "This section contains recommendations for configuring AWS EKS resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "eks",
|
||||
"Section": "EKS",
|
||||
"Service": "eks"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "elastic-beanstalk",
|
||||
"Name": "Benchmark: Elastic Beanstalk",
|
||||
"Description": "This section contains recommendations for configuring AWS Elastic Beanstalk resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "elastic-beanstalk",
|
||||
"Section": "Elastic Beanstalk",
|
||||
"Service": "elasticbeanstalk"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "elb",
|
||||
"Name": "Benchmark: ELB",
|
||||
"Description": "This section contains recommendations for configuring Elastic Load Balancer resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "elb",
|
||||
"Section": "ELB",
|
||||
"Service": "elb"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"elbv2_logging_enabled",
|
||||
"elb_logging_enabled",
|
||||
"elbv2_deletion_protection",
|
||||
"elbv2_desync_mitigation_mode"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "elbv2",
|
||||
"Name": "Benchmark: ELBv2",
|
||||
"Description": "This section contains recommendations for configuring Elastic Load Balancer resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "elbv2",
|
||||
"Section": "ELBv2",
|
||||
"Service": "elbv2"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "emr",
|
||||
"Name": "Benchmark: EMR",
|
||||
"Description": "This section contains recommendations for configuring EMR resources.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "emr",
|
||||
"Section": "EMR",
|
||||
"Service": "emr"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"emr_cluster_master_nodes_no_public_ip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "elasticsearch",
|
||||
"Name": "Benchmark: Elasticsearch",
|
||||
"Description": "This section contains recommendations for configuring Elasticsearch resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "elasticsearch",
|
||||
"Section": "ElasticSearch",
|
||||
"Service": "elasticsearch"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"opensearch_service_domains_encryption_at_rest_enabled",
|
||||
"opensearch_service_domains_node_to_node_encryption_enabled",
|
||||
"opensearch_service_domains_audit_logging_enabled",
|
||||
"opensearch_service_domains_audit_logging_enabled",
|
||||
"opensearch_service_domains_https_communications_enforced"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "guardduty",
|
||||
"Name": "Benchmark: GuardDuty",
|
||||
"Description": "This section contains recommendations for configuring AWS GuardDuty resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "guardduty",
|
||||
"Section": "GuardDuty",
|
||||
"Service": "guardduty"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "iam",
|
||||
"Name": "Benchmark: IAM",
|
||||
"Description": "This section contains recommendations for configuring AWS IAM resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "iam",
|
||||
"Section": "IAM",
|
||||
"Service": "iam"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_rotate_access_key_90_days",
|
||||
"iam_no_root_access_key",
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_root_hardware_mfa_enabled",
|
||||
"iam_password_policy_minimum_length_14",
|
||||
"iam_disable_90_days_credentials",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "kinesis",
|
||||
"Name": "Benchmark: Kinesis",
|
||||
"Description": "This section contains recommendations for configuring AWS Kinesis resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "kinesis",
|
||||
"Section": "Kinesis",
|
||||
"Service": "kinesis"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "kms",
|
||||
"Name": "Benchmark: KMS",
|
||||
"Description": "This section contains recommendations for configuring AWS KMS resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "kms",
|
||||
"Section": "KMS",
|
||||
"Service": "kms"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "lambda",
|
||||
"Name": "Benchmark: Lambda",
|
||||
"Description": "This section contains recommendations for configuring Lambda resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "lambda",
|
||||
"Section": "Lambda",
|
||||
"Service": "lambda"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"awslambda_function_url_public",
|
||||
"awslambda_function_using_supported_runtimes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "network-firewall",
|
||||
"Name": "Benchmark: Network Firewall",
|
||||
"Description": "This section contains recommendations for configuring Network Firewall resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "network-firewall",
|
||||
"Section": "Network Firewall",
|
||||
"Service": "network-firewall"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "opensearch",
|
||||
"Name": "Benchmark: OpenSearch",
|
||||
"Description": "This section contains recommendations for configuring OpenSearch resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "opensearch",
|
||||
"Section": "OpenSearch",
|
||||
"Service": "opensearch"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"opensearch_service_domains_not_publicly_accessible"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "rds",
|
||||
"Name": "Benchmark: RDS",
|
||||
"Description": "This section contains recommendations for configuring AWS RDS resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "rds",
|
||||
"Section": "RDS",
|
||||
"Service": "rds"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_snapshots_public_access",
|
||||
"rds_instance_no_public_access",
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_instance_multi_az",
|
||||
"rds_instance_enhanced_monitoring_enabled",
|
||||
"rds_instance_deletion_protection",
|
||||
"rds_instance_integration_cloudwatch_logs",
|
||||
"rds_instance_minor_version_upgrade_enabled",
|
||||
"rds_instance_multi_az"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "redshift",
|
||||
"Name": "Benchmark: Redshift",
|
||||
"Description": "This section contains recommendations for configuring AWS Redshift resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "redshift",
|
||||
"Section": "Redshift",
|
||||
"Service": "redshift"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"redshift_cluster_public_access",
|
||||
"redshift_cluster_automated_snapshot",
|
||||
"redshift_cluster_automated_snapshot",
|
||||
"redshift_cluster_automatic_upgrades"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "s3",
|
||||
"Name": "Benchmark: S3",
|
||||
"Description": "This section contains recommendations for configuring AWS S3 resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "s3",
|
||||
"Section": "S3",
|
||||
"Service": "s3"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"s3_account_level_public_access_blocks",
|
||||
"s3_account_level_public_access_blocks",
|
||||
"s3_bucket_policy_public_write_access",
|
||||
"s3_bucket_default_encryption",
|
||||
"s3_bucket_secure_transport_policy",
|
||||
"s3_bucket_public_access",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"s3_bucket_object_versioning",
|
||||
"s3_bucket_acl_prohibited"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "sagemaker",
|
||||
"Name": "Benchmark: SageMaker",
|
||||
"Description": "This section contains recommendations for configuring AWS Sagemaker resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "sagemaker",
|
||||
"Section": "SageMaker",
|
||||
"Service": "sagemaker"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"sagemaker_notebook_instance_without_direct_internet_access_configured",
|
||||
"sagemaker_notebook_instance_vpc_settings_configured",
|
||||
"sagemaker_notebook_instance_root_access_disabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "secretsmanager",
|
||||
"Name": "Benchmark: Secrets Manager",
|
||||
"Description": "This section contains recommendations for configuring AWS Secrets Manager resources.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "secretsmanager",
|
||||
"Section": "Secrets Manager",
|
||||
"Service": "secretsmanager"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"secretsmanager_automatic_rotation_enabled",
|
||||
"secretsmanager_automatic_rotation_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "sns",
|
||||
"Name": "Benchmark: SNS",
|
||||
"Description": "This section contains recommendations for configuring AWS SNS resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "sns",
|
||||
"Section": "SNS",
|
||||
"Service": "sns"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"sns_topics_kms_encryption_at_rest_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "sqs",
|
||||
"Name": "Benchmark: SQS",
|
||||
"Description": "This section contains recommendations for configuring AWS SQS resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "sqs",
|
||||
"Section": "SQS",
|
||||
"Service": "sqs"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"sqs_queues_server_side_encryption_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "ssm",
|
||||
"Name": "Benchmark: SSM",
|
||||
"Description": "This section contains recommendations for configuring AWS Systems Manager resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ssm",
|
||||
"Section": "SSM",
|
||||
"Service": "ssm"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_instance_managed_by_ssm",
|
||||
"ssm_managed_compliant_patching",
|
||||
"ssm_managed_compliant_patching"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "waf",
|
||||
"Name": "Benchmark: WAF",
|
||||
"Description": "This section contains recommendations for configuring AWS WAF resources and options.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "waf",
|
||||
"Section": "WAF",
|
||||
"Service": "waf"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"Framework": "AWS-Well-Architected-Framework-Reliability-Pillar",
|
||||
"Version": "",
|
||||
"Provider": "AWS",
|
||||
"Description": "Best Practices for the AWS Well-Architected Framework Reliability Pillar encompasses the ability of a workload to perform its intended function correctly and consistently when it’s expected to. This includes the ability to operate and test the workload through its total lifecycle.",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "REL09-BP03",
|
||||
"Description": "Configure backups to be taken automatically based on a periodic schedule informed by the Recovery Point Objective (RPO), or by changes in the dataset. Critical datasets with low data loss requirements need to be backed up automatically on a frequent basis, whereas less critical data where some loss is acceptable can be backed up less frequently.",
|
||||
"Attributes": [
|
||||
{
|
||||
"Name": "REL09-BP03 Perform data backup automatically",
|
||||
"WellArchitectedQuestionId": "backing-up-data",
|
||||
"WellArchitectedPracticeId": "rel_backing_up_data_automated_backups_data",
|
||||
"Section": "Failure management",
|
||||
"SubSection": "Backup up data",
|
||||
"LevelOfRisk": "High",
|
||||
"AssessmentMethod": "Automated",
|
||||
"Description": "Configure backups to be taken automatically based on a periodic schedule informed by the Recovery Point Objective (RPO), or by changes in the dataset. Critical datasets with low data loss requirements need to be backed up automatically on a frequent basis, whereas less critical data where some loss is acceptable can be backed up less frequently.",
|
||||
"ImplementationGuidanceUrl": "https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_backing_up_data_automated_backups_data.html#implementation-guidance"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudformation_stacks_termination_protection_enabled",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_deletion_protection",
|
||||
"dynamodb_tables_pitr_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "REL06-BP01",
|
||||
"Description": "Monitor components and services of AWS workload effectifely, using tools like Amazon CloudWatch and AWS Health Dashboard. Define relevant metrics, set thresholds, and analyze metrics and logs for early detection of issues.",
|
||||
"Attributes": [
|
||||
{
|
||||
"Name": "REL06-BP01 Monitor all components for the workload (Generation)",
|
||||
"WellArchitectedQuestionId": "monitor-aws-resources",
|
||||
"WellArchitectedPracticeId": "rel_monitor_aws_resources_monitor_resources",
|
||||
"Section": "Change management",
|
||||
"SubSection": "Monitor workload resources",
|
||||
"LevelOfRisk": "High",
|
||||
"AssessmentMethod": "Automated",
|
||||
"Description": "Monitor components and services of AWS workload effectifely, using tools like Amazon CloudWatch and AWS Health Dashboard. Define relevant metrics, set thresholds, and analyze metrics and logs for early detection of issues.",
|
||||
"ImplementationGuidanceUrl": "https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_monitor_aws_resources_monitor_resources.html#implementation-guidance"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"apigatewayv2_access_logging_enabled",
|
||||
"awslambda_function_invoke_api_operations_cloudtrail_logging_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"elb_logging_enabled",
|
||||
"opensearch_service_domains_audit_logging_enabled",
|
||||
"opensearch_service_domains_cloudwatch_logging_enabled",
|
||||
"rds_instance_enhanced_monitoring_enabled",
|
||||
"rds_instance_integration_cloudwatch_logs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "REL10-BP01",
|
||||
"Description": "Distribute workload data and resources across multiple Availability Zones or, where necessary, across AWS Regions. These locations can be as diverse as required.",
|
||||
"Attributes": [
|
||||
{
|
||||
"Name": "REL10-BP01 Deploy the workload to multiple locations",
|
||||
"WellArchitectedQuestionId": "fault-isolation",
|
||||
"WellArchitectedPracticeId": "rel_fault_isolation_multiaz_region_system",
|
||||
"Section": "Failure management",
|
||||
"SubSection": "Use fault isolation to protect your workload",
|
||||
"LevelOfRisk": "High",
|
||||
"AssessmentMethod": "Automated",
|
||||
"Description": "Distribute workload data and resources across multiple Availability Zones or, where necessary, across AWS Regions. These locations can be as diverse as required.",
|
||||
"ImplementationGuidanceUrl": "https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/use-fault-isolation-to-protect-your-workload.html#implementation-guidance."
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_multi_az"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"Framework": "CIS-AWS",
|
||||
"Framework": "CIS",
|
||||
"Version": "1.4",
|
||||
"Provider": "AWS",
|
||||
"Description": "The CIS Benchmark for CIS Amazon Web Services Foundations Benchmark, v1.4.0, Level 1 and 2 provides prescriptive guidance for configuring security options for a subset of Amazon Web Services. It has an emphasis on foundational, testable, and architecture agnostic settings",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "1.1",
|
||||
@@ -153,7 +155,8 @@
|
||||
"Id": "1.16",
|
||||
"Description": "Ensure IAM policies that allow full \"*:*\" administrative privileges are not attached",
|
||||
"Checks": [
|
||||
"iam_policy_no_administrative_privileges"
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
@@ -258,7 +261,7 @@
|
||||
"Id": "1.20",
|
||||
"Description": "Ensure that IAM Access analyzer is enabled for all regions",
|
||||
"Checks": [
|
||||
"accessanalyzer_enabled_without_findings"
|
||||
"accessanalyzer_enabled"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
@@ -531,6 +534,7 @@
|
||||
"Id": "2.1.5",
|
||||
"Description": "Ensure that S3 Buckets are configured with 'Block public access (bucket settings)'",
|
||||
"Checks": [
|
||||
"s3_bucket_level_public_access_block",
|
||||
"s3_account_level_public_access_blocks"
|
||||
],
|
||||
"Attributes": [
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"Framework": "CIS-AWS",
|
||||
"Framework": "CIS",
|
||||
"Version": "1.5",
|
||||
"Provider": "AWS",
|
||||
"Description": "The CIS Amazon Web Services Foundations Benchmark provides prescriptive guidance for configuring security options for a subset of Amazon Web Services with an emphasis on foundational, testable, and architecture agnostic settings.",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "1.1",
|
||||
@@ -153,7 +155,8 @@
|
||||
"Id": "1.16",
|
||||
"Description": "Ensure IAM policies that allow full \"*:*\" administrative privileges are not attached",
|
||||
"Checks": [
|
||||
"iam_policy_no_administrative_privileges"
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
@@ -258,7 +261,7 @@
|
||||
"Id": "1.20",
|
||||
"Description": "Ensure that IAM Access analyzer is enabled for all regions",
|
||||
"Checks": [
|
||||
"accessanalyzer_enabled_without_findings"
|
||||
"accessanalyzer_enabled"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
@@ -531,6 +534,7 @@
|
||||
"Id": "2.1.5",
|
||||
"Description": "Ensure that S3 Buckets are configured with 'Block public access (bucket settings)'",
|
||||
"Checks": [
|
||||
"s3_bucket_level_public_access_block",
|
||||
"s3_account_level_public_access_blocks"
|
||||
],
|
||||
"Attributes": [
|
||||
|
||||
1379
prowler/compliance/aws/cis_2.0_aws.json
Normal file
425
prowler/compliance/aws/cisa_aws.json
Normal file
@@ -0,0 +1,425 @@
|
||||
{
|
||||
"Framework": "CISA",
|
||||
"Version": "",
|
||||
"Provider": "AWS",
|
||||
"Description": "Cybersecurity & Infrastructure Security Agency's (CISA) Cyber Essentials is a guide for leaders of small businesses as well as leaders of small and local government agencies to develop an actionable understanding of where to start implementing organizational cybersecurity practices.",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "your-systems-1",
|
||||
"Name": "Your Systems-1",
|
||||
"Description": "Learn what is on your network. Maintain inventories of hardware and software assets to know what is in play and at-risk from attack.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-systems-1",
|
||||
"Section": "your systems",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_instance_managed_by_ssm",
|
||||
"ec2_instance_older_than_specific_days",
|
||||
"ssm_managed_compliant_patching",
|
||||
"ec2_elastic_ip_unassgined"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-systems-2",
|
||||
"Name": "Your Systems-2",
|
||||
"Description": "Leverage automatic updates for all operating systems and third-party software.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-systems-2",
|
||||
"Section": "your systems",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_minor_version_upgrade_enabled",
|
||||
"redshift_cluster_automatic_upgrades",
|
||||
"ssm_managed_compliant_patching"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-systems-3",
|
||||
"Name": "Your Systems-3",
|
||||
"Description": "Implement security configurations for all hardware and software assets.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-systems-3",
|
||||
"Section": "your systems",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_client_certificate_enabled",
|
||||
"apigateway_logging_enabled",
|
||||
"apigateway_waf_acl_attached",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_kms_encryption_enabled",
|
||||
"cloudtrail_log_file_validation_enabled",
|
||||
"codebuild_project_user_controlled_buildspec",
|
||||
"dynamodb_accelerator_cluster_encryption_enabled",
|
||||
"dynamodb_tables_kms_cmk_encryption_enabled",
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"ec2_ebs_volume_encryption",
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_ebs_default_encryption",
|
||||
"ec2_instance_public_ip",
|
||||
"efs_encryption_at_rest_enabled",
|
||||
"efs_have_backup_enabled",
|
||||
"elb_logging_enabled",
|
||||
"elbv2_deletion_protection",
|
||||
"elbv2_waf_acl_attached",
|
||||
"elbv2_ssl_listeners",
|
||||
"elb_ssl_listeners",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"opensearch_service_domains_encryption_at_rest_enabled",
|
||||
"opensearch_service_domains_cloudwatch_logging_enabled",
|
||||
"opensearch_service_domains_node_to_node_encryption_enabled",
|
||||
"guardduty_is_enabled",
|
||||
"iam_password_policy_minimum_length_14",
|
||||
"iam_password_policy_lowercase",
|
||||
"iam_password_policy_number",
|
||||
"iam_password_policy_number",
|
||||
"iam_password_policy_symbol",
|
||||
"iam_password_policy_uppercase",
|
||||
"iam_no_custom_policy_permissive_role_assumption",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges",
|
||||
"iam_root_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled",
|
||||
"iam_no_root_access_key",
|
||||
"iam_rotate_access_key_90_days",
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_disable_90_days_credentials",
|
||||
"kms_cmk_rotation_enabled",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"cloudwatch_log_group_kms_encryption_enabled",
|
||||
"cloudwatch_log_group_kms_encryption_enabled",
|
||||
"rds_instance_enhanced_monitoring_enabled",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_deletion_protection",
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_integration_cloudwatch_logs",
|
||||
"rds_instance_multi_az",
|
||||
"rds_instance_no_public_access",
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_snapshots_public_access",
|
||||
"redshift_cluster_automated_snapshot",
|
||||
"redshift_cluster_audit_logging",
|
||||
"redshift_cluster_public_access",
|
||||
"s3_bucket_default_encryption",
|
||||
"s3_bucket_secure_transport_policy",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"s3_bucket_public_access",
|
||||
"s3_bucket_policy_public_write_access",
|
||||
"s3_bucket_object_versioning",
|
||||
"s3_account_level_public_access_blocks",
|
||||
"s3_bucket_public_access",
|
||||
"sagemaker_training_jobs_volume_and_output_encryption_enabled",
|
||||
"sagemaker_notebook_instance_without_direct_internet_access_configured",
|
||||
"sagemaker_notebook_instance_encryption_enabled",
|
||||
"secretsmanager_automatic_rotation_enabled",
|
||||
"securityhub_enabled",
|
||||
"sns_topics_kms_encryption_at_rest_enabled",
|
||||
"vpc_endpoint_connections_trust_boundaries",
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your_-urroundings-1",
|
||||
"Name": "Your Surroundings-1",
|
||||
"Description": "Learn who is on your network. Maintain inventories of network connections (user accounts, vendors, business partners, etc.).",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-surroundings-1",
|
||||
"Section": "your surroundings",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_elastic_ip_unassgined",
|
||||
"vpc_flow_logs_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-surroundings-2",
|
||||
"Name": "Your Surroundings-2",
|
||||
"Description": "Leverage multi-factor authentication for all users, starting with privileged, administrative and remote access users.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-surroundings-2",
|
||||
"Section": "your surroundings",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_root_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled",
|
||||
"iam_user_mfa_enabled_console_access"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-surroundings-3",
|
||||
"Name": "Your Surroundings-3",
|
||||
"Description": "Grant access and admin permissions based on need-to-know and least privilege.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-surroundings-3",
|
||||
"Section": "your surroundings",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"elbv2_ssl_listeners",
|
||||
"iam_no_custom_policy_permissive_role_assumption",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges",
|
||||
"iam_no_root_access_key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-surroundings-4",
|
||||
"Name": "Your Surroundings-4",
|
||||
"Description": "Leverage unique passwords for all user accounts.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-surroundings-4",
|
||||
"Section": "your surroundings",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_password_policy_minimum_length_14",
|
||||
"iam_password_policy_lowercase",
|
||||
"iam_password_policy_number",
|
||||
"iam_password_policy_number",
|
||||
"iam_password_policy_symbol",
|
||||
"iam_password_policy_uppercase"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-data-1",
|
||||
"Name": "Your Data-1",
|
||||
"Description": "Learn how your data is protected.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-data-1",
|
||||
"Section": "your data",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"efs_encryption_at_rest_enabled",
|
||||
"cloudtrail_kms_encryption_enabled",
|
||||
"dynamodb_tables_kms_cmk_encryption_enabled",
|
||||
"ec2_ebs_volume_encryption",
|
||||
"ec2_ebs_default_encryption",
|
||||
"opensearch_service_domains_encryption_at_rest_enabled",
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_instance_storage_encrypted",
|
||||
"redshift_cluster_audit_logging",
|
||||
"s3_bucket_default_encryption",
|
||||
"sagemaker_training_jobs_volume_and_output_encryption_enabled",
|
||||
"sagemaker_notebook_instance_encryption_enabled",
|
||||
"sns_topics_kms_encryption_at_rest_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-data-2",
|
||||
"Name": "Your Data-2",
|
||||
"Description": "Learn what is happening on your network, manage network and perimeter components, host and device components, data-at-rest and in-transit, and user behavior activities.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-data-2",
|
||||
"Section": "your data",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"acm_certificates_expiration_check",
|
||||
"apigateway_client_certificate_enabled",
|
||||
"apigateway_logging_enabled",
|
||||
"efs_have_backup_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled",
|
||||
"cloudwatch_log_group_kms_encryption_enabled",
|
||||
"dynamodb_tables_kms_cmk_encryption_enabled",
|
||||
"ec2_ebs_volume_encryption",
|
||||
"ec2_instance_public_ip",
|
||||
"efs_encryption_at_rest_enabled",
|
||||
"elb_logging_enabled",
|
||||
"elbv2_waf_acl_attached",
|
||||
"elbv2_ssl_listeners",
|
||||
"elb_ssl_listeners",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"opensearch_service_domains_encryption_at_rest_enabled",
|
||||
"opensearch_service_domains_cloudwatch_logging_enabled",
|
||||
"opensearch_service_domains_node_to_node_encryption_enabled",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"cloudwatch_log_group_kms_encryption_enabled",
|
||||
"rds_instance_storage_encrypted",
|
||||
"rds_instance_integration_cloudwatch_logs",
|
||||
"rds_instance_no_public_access",
|
||||
"rds_snapshots_public_access",
|
||||
"rds_snapshots_public_access",
|
||||
"redshift_cluster_audit_logging",
|
||||
"redshift_cluster_public_access",
|
||||
"s3_bucket_default_encryption",
|
||||
"s3_bucket_secure_transport_policy",
|
||||
"redshift_cluster_public_access",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"s3_bucket_public_access",
|
||||
"s3_bucket_policy_public_write_access",
|
||||
"s3_account_level_public_access_blocks",
|
||||
"s3_bucket_acl_prohibited",
|
||||
"sagemaker_training_jobs_volume_and_output_encryption_enabled",
|
||||
"sagemaker_notebook_instance_without_direct_internet_access_configured",
|
||||
"sagemaker_notebook_instance_encryption_enabled",
|
||||
"sns_topics_kms_encryption_at_rest_enabled",
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"vpc_flow_logs_enabled",
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-data-3",
|
||||
"Name": "Your Data-3",
|
||||
"Description": "Domain name system protection.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-data-3",
|
||||
"Section": "your data",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"elbv2_waf_acl_attached"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-data-4",
|
||||
"Name": "Your Data-4",
|
||||
"Description": "Establish regular automated backups and redundancies of key systems.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-data-4",
|
||||
"Section": "your data",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"efs_have_backup_enabled",
|
||||
"elbv2_deletion_protection",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_deletion_protection",
|
||||
"rds_instance_backup_enabled",
|
||||
"redshift_cluster_automated_snapshot",
|
||||
"s3_bucket_object_versioning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "your-data-5",
|
||||
"Name": "Your Data-5",
|
||||
"Description": "Leverage protections for backups, including physical security, encryption and offline copies.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-data-5",
|
||||
"Section": "your data",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "your-crisis-response-2",
|
||||
"Name": "Your Crisis Response-2",
|
||||
"Description": "Lead development of an internal reporting structure to detect, communicate and contain attacks.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "your-crisis-response-2",
|
||||
"Section": "your crisis response",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "booting-up-thing-to-do-first-1",
|
||||
"Name": "YBooting Up: Things to Do First-1",
|
||||
"Description": "Lead development of an internal reporting structure to detect, communicate and contain attacks.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "booting-up-thing-to-do-first-1",
|
||||
"Section": "booting up thing to do first",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"efs_have_backup_enabled",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_backup_enabled",
|
||||
"redshift_cluster_automated_snapshot",
|
||||
"s3_bucket_object_versioning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "booting-up-thing-to-do-first-2",
|
||||
"Name": "YBooting Up: Things to Do First-2",
|
||||
"Description": "Require multi-factor authentication (MFA) for accessing your systems whenever possible. MFA should be required of all users, but start with privileged, administrative, and remote access users.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "booting-up-thing-to-do-first-2",
|
||||
"Section": "booting up thing to do first",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_user_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled",
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_user_hardware_mfa_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "booting-up-thing-to-do-first-3",
|
||||
"Name": "YBooting Up: Things to Do First-3",
|
||||
"Description": "Enable automatic updates whenever possible. Replace unsupported operating systems, applications and hardware. Test and deploy patches quickly.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "booting-up-thing-to-do-first-1",
|
||||
"Section": "booting up thing to do first",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_minor_version_upgrade_enabled",
|
||||
"redshift_cluster_automatic_upgrades",
|
||||
"ssm_managed_compliant_patching"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
442
prowler/compliance/aws/fedramp_low_revision_4_aws.json
Normal file
@@ -0,0 +1,442 @@
|
||||
{
|
||||
"Framework": "FedRAMP-Low-Revision-4",
|
||||
"Version": "",
|
||||
"Provider": "AWS",
|
||||
"Description": "The Federal Risk and Authorization Management Program (FedRAMP) was established in 2011. It provides a cost-effective, risk-based approach for the adoption and use of cloud services by the U.S. federal government. FedRAMP empowers federal agencies to use modern cloud technologies, with an emphasis on the security and protection of federal information.",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "ac-2",
|
||||
"Name": "Account Management (AC-2)",
|
||||
"Description": "Manage system accounts, group memberships, privileges, workflow, notifications, deactivations, and authorizations.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ac-2",
|
||||
"Section": "Access Control (AC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_log_file_validation_enabled",
|
||||
"cloudwatch_changes_to_network_acls_alarm_configured",
|
||||
"opensearch_service_domains_cloudwatch_logging_enabled",
|
||||
"guardduty_is_enabled",
|
||||
"iam_password_policy_minimum_length_14",
|
||||
"iam_policy_attached_only_to_group_or_roles",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges",
|
||||
"iam_root_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled",
|
||||
"iam_no_root_access_key",
|
||||
"iam_rotate_access_key_90_days",
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_user_hardware_mfa_enabled",
|
||||
"iam_disable_90_days_credentials",
|
||||
"rds_instance_integration_cloudwatch_logs",
|
||||
"redshift_cluster_audit_logging",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "ac-3",
|
||||
"Name": "Account Management (AC-3)",
|
||||
"Description": "The information system enforces approved authorizations for logical access to information and system resources in accordance with applicable access control policies.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ac-3",
|
||||
"Section": "Access Control (AC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_instance_public_ip",
|
||||
"ec2_instance_imdsv2_enabled",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"iam_policy_attached_only_to_group_or_roles",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges",
|
||||
"iam_no_root_access_key",
|
||||
"iam_disable_90_days_credentials",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"awslambda_function_url_public",
|
||||
"rds_instance_no_public_access",
|
||||
"rds_snapshots_public_access",
|
||||
"redshift_cluster_public_access",
|
||||
"s3_bucket_policy_public_write_access",
|
||||
"s3_account_level_public_access_blocks",
|
||||
"s3_bucket_public_access",
|
||||
"sagemaker_notebook_instance_without_direct_internet_access_configured"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "ac-17",
|
||||
"Name": "Remote Access (AC-17)",
|
||||
"Description": "Authorize remote access systems prior to connection. Enforce remote connection requirements to information systems.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ac-17",
|
||||
"Section": "Access Control (AC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"acm_certificates_expiration_check",
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_instance_public_ip",
|
||||
"elb_ssl_listeners",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"guardduty_is_enabled",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"awslambda_function_url_public",
|
||||
"rds_instance_no_public_access",
|
||||
"rds_snapshots_public_access",
|
||||
"redshift_cluster_public_access",
|
||||
"s3_bucket_secure_transport_policy",
|
||||
"s3_bucket_policy_public_write_access",
|
||||
"s3_account_level_public_access_blocks",
|
||||
"s3_bucket_public_access",
|
||||
"sagemaker_notebook_instance_without_direct_internet_access_configured",
|
||||
"securityhub_enabled",
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_networkacl_allow_ingress_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "au-2",
|
||||
"Name": "Audit Events (AU-2)",
|
||||
"Description": "The organization: a. Determines that the information system is capable of auditing the following events: [Assignment: organization-defined auditable events]; b. Coordinates the security audit function with other organizational entities requiring audit- related information to enhance mutual support and to help guide the selection of auditable events; c. Provides a rationale for why the auditable events are deemed to be adequate support after- the-fact investigations of security incidents",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "au-2",
|
||||
"Section": "Audit and Accountability (AU)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_log_file_validation_enabled",
|
||||
"elbv2_logging_enabled",
|
||||
"rds_instance_integration_cloudwatch_logs",
|
||||
"redshift_cluster_audit_logging",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"vpc_flow_logs_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "au-9",
|
||||
"Name": "Protection of Audit Information (AU-9)",
|
||||
"Description": "The information system protects audit information and audit tools from unauthorized access, modification, and deletion.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "au-9",
|
||||
"Section": "Audit and Accountability (AU)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudtrail_kms_encryption_enabled",
|
||||
"cloudtrail_log_file_validation_enabled",
|
||||
"cloudwatch_log_group_kms_encryption_enabled",
|
||||
"s3_bucket_object_versioning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "au-11",
|
||||
"Name": "Audit Record Retention (AU-11)",
|
||||
"Description": "The organization retains audit records for at least 90 days to provide support for after-the-fact investigations of security incidents and to meet regulatory and organizational information retention requirements.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "au-11",
|
||||
"Section": "Audit and Accountability (AU)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudwatch_log_group_retention_policy_specific_days_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "ca-7",
|
||||
"Name": "Continuous Monitoring (CA-7)",
|
||||
"Description": "Continuously monitor configuration management processes. Determine security impact, environment and operational risks.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ca-7",
|
||||
"Section": "Security Assessment And Authorization (CA)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudwatch_changes_to_network_acls_alarm_configured",
|
||||
"ec2_instance_imdsv2_enabled",
|
||||
"elbv2_waf_acl_attached",
|
||||
"guardduty_is_enabled",
|
||||
"rds_instance_enhanced_monitoring_enabled",
|
||||
"redshift_cluster_audit_logging",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "cm-2",
|
||||
"Name": "Baseline Configuration (CM-2)",
|
||||
"Description": "The organization develops, documents, and maintains under configuration control, a current baseline configuration of the information system.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "cm-2",
|
||||
"Section": "Configuration Management (CM)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_waf_acl_attached",
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_instance_public_ip",
|
||||
"ec2_instance_older_than_specific_days",
|
||||
"elbv2_deletion_protection",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"awslambda_function_url_public",
|
||||
"rds_instance_no_public_access",
|
||||
"rds_snapshots_public_access",
|
||||
"redshift_cluster_public_access",
|
||||
"s3_bucket_public_access",
|
||||
"s3_bucket_policy_public_write_access",
|
||||
"s3_account_level_public_access_blocks",
|
||||
"s3_bucket_public_access",
|
||||
"sagemaker_notebook_instance_without_direct_internet_access_configured",
|
||||
"ssm_managed_compliant_patching",
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_networkacl_allow_ingress_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "cm-8",
|
||||
"Name": "Information System Component Inventory (CM-8)",
|
||||
"Description": "The organization develops and documents an inventory of information system components that accurately reflects the current information system, includes all components within the authorization boundary of the information system, is at the level of granularity deemed necessary for tracking and reporting and reviews and updates the information system component inventory.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "cm-8",
|
||||
"Section": "Configuration Management (CM)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_instance_managed_by_ssm",
|
||||
"guardduty_is_enabled",
|
||||
"ssm_managed_compliant_patching",
|
||||
"ssm_managed_compliant_patching"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "cp-9",
|
||||
"Name": "Information System Backup (CP-9)",
|
||||
"Description": "The organization conducts backups of user-level information, system-level information and information system documentation including security-related documentation contained in the information system and protects the confidentiality, integrity, and availability of backup information at storage locations.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "cp-9",
|
||||
"Section": "Contingency Planning (CP)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"efs_have_backup_enabled",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_backup_enabled",
|
||||
"redshift_cluster_automated_snapshot",
|
||||
"s3_bucket_object_versioning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "cp-10",
|
||||
"Name": "Information System Recovery And Reconstitution (CP-10)",
|
||||
"Description": "The organization provides for the recovery and reconstitution of the information system to a known state after a disruption, compromise, or failure.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "cp-10",
|
||||
"Section": "Contingency Planning (CP)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"efs_have_backup_enabled",
|
||||
"elbv2_deletion_protection",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_multi_az",
|
||||
"rds_instance_backup_enabled",
|
||||
"redshift_cluster_automated_snapshot",
|
||||
"s3_bucket_object_versioning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "ia-2",
|
||||
"Name": "Identification and Authentication (Organizational users) (IA-2)",
|
||||
"Description": "The information system uniquely identifies and authenticates organizational users (or processes acting on behalf of organizational users).",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ia-2",
|
||||
"Section": "Identification and Authentication (IA)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_password_policy_minimum_length_14",
|
||||
"iam_root_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled",
|
||||
"iam_no_root_access_key",
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_user_mfa_enabled_console_access"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "ir-4",
|
||||
"Name": "Incident Handling (IR-4)",
|
||||
"Description": "The organization implements an incident handling capability for security incidents that includes preparation, detection and analysis, containment, eradication, and recovery, coordinates incident handling activities with contingency planning activities and incorporates lessons learned from ongoing incident handling activities into incident response procedures, training, and testing, and implements the resulting changes accordingly.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "ir-4",
|
||||
"Section": "Incident Response (IR)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudwatch_changes_to_network_acls_alarm_configured",
|
||||
"cloudwatch_changes_to_network_gateways_alarm_configured",
|
||||
"cloudwatch_changes_to_network_route_tables_alarm_configured",
|
||||
"cloudwatch_changes_to_vpcs_alarm_configured",
|
||||
"guardduty_is_enabled",
|
||||
"guardduty_no_high_severity_findings",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "sa-3",
|
||||
"Name": "System Development Life Cycle (SA-3)",
|
||||
"Description": "The organization manages the information system using organization-defined system development life cycle, defines and documents information security roles and responsibilities throughout the system development life cycle, identifies individuals having information security roles and responsibilities and integrates the organizational information security risk management process into system development life cycle activities.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "sa-3",
|
||||
"Section": "System and Services Acquisition (SA)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_instance_managed_by_ssm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "sc-5",
|
||||
"Name": "Denial Of Service Protection (SC-5)",
|
||||
"Description": "The information system protects against or limits the effects of the following types of denial of service attacks: [Assignment: organization-defined types of denial of service attacks or references to sources for such information] by employing [Assignment: organization-defined security safeguards].",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "sc-5",
|
||||
"Section": "System and Communications Protection (SC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"elbv2_deletion_protection",
|
||||
"guardduty_is_enabled",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_deletion_protection",
|
||||
"rds_instance_multi_az",
|
||||
"redshift_cluster_automated_snapshot",
|
||||
"s3_bucket_object_versioning"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "sc-7",
|
||||
"Name": "Boundary Protection (SC-7)",
|
||||
"Description": "The information system: a. Monitors and controls communications at the external boundary of the system and at key internal boundaries within the system; b. Implements subnetworks for publicly accessible system components that are [Selection: physically; logically] separated from internal organizational networks; and c. Connects to external networks or information systems only through managed interfaces consisting of boundary protection devices arranged in accordance with an organizational security architecture.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "sc-7",
|
||||
"Section": "System and Communications Protection (SC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_instance_public_ip",
|
||||
"elbv2_waf_acl_attached",
|
||||
"elb_ssl_listeners",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"opensearch_service_domains_node_to_node_encryption_enabled",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"awslambda_function_url_public",
|
||||
"rds_instance_no_public_access",
|
||||
"rds_snapshots_public_access",
|
||||
"redshift_cluster_public_access",
|
||||
"s3_bucket_secure_transport_policy",
|
||||
"s3_bucket_public_access",
|
||||
"s3_bucket_policy_public_write_access",
|
||||
"s3_account_level_public_access_blocks",
|
||||
"s3_bucket_public_access",
|
||||
"sagemaker_notebook_instance_without_direct_internet_access_configured",
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_networkacl_allow_ingress_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "sc-12",
|
||||
"Name": "Cryptographic Key Establishment And Management (SC-12)",
|
||||
"Description": "The organization establishes and manages cryptographic keys for required cryptography employed within the information system in accordance with [Assignment: organization-defined requirements for key generation, distribution, storage, access, and destruction].",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "sc-12",
|
||||
"Section": "System and Communications Protection (SC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"acm_certificates_expiration_check",
|
||||
"kms_cmk_rotation_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "sc-13",
|
||||
"Name": "Use of Cryptography (SC-13)",
|
||||
"Description": "The information system implements FIPS-validated or NSA-approved cryptography in accordance with applicable federal laws, Executive Orders, directives, policies, regulations, and standards.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "sc-13",
|
||||
"Section": "System and Communications Protection (SC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"s3_bucket_default_encryption",
|
||||
"sagemaker_training_jobs_volume_and_output_encryption_enabled",
|
||||
"sagemaker_notebook_instance_encryption_enabled",
|
||||
"sns_topics_kms_encryption_at_rest_enabled"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
1442
prowler/compliance/aws/fedramp_moderate_revision_4_aws.json
Normal file
908
prowler/compliance/aws/ffiec_aws.json
Normal file
@@ -0,0 +1,908 @@
|
||||
{
|
||||
"Framework": "FFIEC",
|
||||
"Version": "",
|
||||
"Provider": "AWS",
|
||||
"Description": "In light of the increasing volume and sophistication of cyber threats, the Federal Financial Institutions Examination Council (FFIEC) developed the Cybersecurity Assessment Tool (Assessment), on behalf of its members, to help institutions identify their risks and determine their cybersecurity maturity.",
|
||||
"Requirements": [
|
||||
{
|
||||
"Id": "d1-g-it-b-1",
|
||||
"Name": "D1.G.IT.B.1",
|
||||
"Description": "An inventory of organizational assets (e.g., hardware, software, data, and systems hosted externally) is maintained.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d1-g-it-b-1",
|
||||
"Section": "Cyber Risk Management and Oversight (Domain 1)",
|
||||
"SubSection": "Governance (G)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_instance_managed_by_ssm",
|
||||
"ec2_instance_older_than_specific_days",
|
||||
"ec2_elastic_ip_unassgined"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d1-rm-ra-b-2",
|
||||
"Name": "D1.RM.RA.B.2",
|
||||
"Description": "The risk assessment identifies Internet- based systems and high-risk transactions that warrant additional authentication controls.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d1-rm-ra-b-2",
|
||||
"Section": "Cyber Risk Management and Oversight (Domain 1)",
|
||||
"SubSection": "Risk Management (RM)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d1-rm-rm-b-1",
|
||||
"Name": "D1.RM.Rm.B.1",
|
||||
"Description": "An information security and business continuity risk management function(s) exists within the institution.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d1-rm-rm-b-1",
|
||||
"Section": "Cyber Risk Management and Oversight (Domain 1)",
|
||||
"SubSection": "Risk Management (RM)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_multi_az",
|
||||
"redshift_cluster_automated_snapshot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d2-is-is-b-1",
|
||||
"Name": "D2.IS.Is.B.1",
|
||||
"Description": "Information security threats are gathered and shared with applicable internal employees.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d2-is-is-b-1",
|
||||
"Section": "Threat Intelligence and Collaboration (Domain 2)",
|
||||
"SubSection": "Information Sharing (IS)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"guardduty_is_enabled",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d2-ma-ma-b-1",
|
||||
"Name": "D2.MA.Ma.B.1",
|
||||
"Description": "Information security threats are gathered and shared with applicable internal employees.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d2-ma-ma-b-1",
|
||||
"Section": "Threat Intelligence and Collaboration (Domain 2)",
|
||||
"SubSection": "Monitoring and Analyzing (MA)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"cloudwatch_log_group_retention_policy_specific_days_enabled",
|
||||
"elbv2_logging_enabled",
|
||||
"elb_logging_enabled",
|
||||
"opensearch_service_domains_cloudwatch_logging_enabled",
|
||||
"rds_instance_integration_cloudwatch_logs",
|
||||
"redshift_cluster_audit_logging",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"vpc_flow_logs_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d2-ma-ma-b-2",
|
||||
"Name": "D2.MA.Ma.B.2",
|
||||
"Description": "Computer event logs are used for investigations once an event has occurred.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d2-ma-ma-b-2",
|
||||
"Section": "Threat Intelligence and Collaboration (Domain 2)",
|
||||
"SubSection": "Monitoring and Analyzing (MA)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"elbv2_logging_enabled",
|
||||
"elb_logging_enabled",
|
||||
"opensearch_service_domains_cloudwatch_logging_enabled",
|
||||
"redshift_cluster_audit_logging",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"vpc_flow_logs_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d2-ti-ti-b-1",
|
||||
"Name": "D2.TI.Ti.B.1",
|
||||
"Description": "The institution belongs or subscribes to a threat and vulnerability information-sharing source(s) that provides information on threats (e.g., FS-ISAC, US- CERT).",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d2-ti-ti-b-1",
|
||||
"Section": "Threat Intelligence and Collaboration (Domain 2)",
|
||||
"SubSection": "Threat Intelligence (TI)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d2-ti-ti-b-2",
|
||||
"Name": "D2.TI.Ti.B.2",
|
||||
"Description": "Threat information is used to monitor threats and vulnerabilities.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d2-ti-ti-b-2",
|
||||
"Section": "Threat Intelligence and Collaboration (Domain 2)",
|
||||
"SubSection": "Threat Intelligence (TI)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled",
|
||||
"securityhub_enabled",
|
||||
"ssm_managed_compliant_patching"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d2-ti-ti-b-3",
|
||||
"Name": "D2.TI.Ti.B.3",
|
||||
"Description": "Threat information is used to enhance internal risk management and controls.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d2-ti-ti-b-3",
|
||||
"Section": "Threat Intelligence and Collaboration (Domain 2)",
|
||||
"SubSection": "Threat Intelligence (TI)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-cc-pm-b-1",
|
||||
"Name": "D3.CC.PM.B.1",
|
||||
"Description": "A patch management program is implemented and ensures that software and firmware patches are applied in a timely manner.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-cc-pm-b-1",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Corrective Controls (CC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_minor_version_upgrade_enabled",
|
||||
"redshift_cluster_automatic_upgrades",
|
||||
"ssm_managed_compliant_patching"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-cc-pm-b-3",
|
||||
"Name": "D3.CC.PM.B.3",
|
||||
"Description": "Patch management reports are reviewed and reflect missing security patches.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-cc-pm-b-3",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Corrective Controls (CC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"rds_instance_minor_version_upgrade_enabled",
|
||||
"redshift_cluster_automatic_upgrades",
|
||||
"ssm_managed_compliant_patching"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-dc-an-b-1",
|
||||
"Name": "D3.DC.An.B.1",
|
||||
"Description": "The institution is able to detect anomalous activities through monitoring across the environment.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-dc-an-b-1",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Detective Controls (DC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled",
|
||||
"guardduty_no_high_severity_findings",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-dc-an-b-2",
|
||||
"Name": "D3.DC.An.B.2",
|
||||
"Description": "Customer transactions generating anomalous activity alerts are monitored and reviewed.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-dc-an-b-2",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Detective Controls (DC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-dc-an-b-3",
|
||||
"Name": "D3.DC.An.B.3",
|
||||
"Description": "Logs of physical and/or logical access are reviewed following events.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-dc-an-b-3",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Detective Controls (DC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"elbv2_logging_enabled",
|
||||
"elb_logging_enabled",
|
||||
"opensearch_service_domains_cloudwatch_logging_enabled",
|
||||
"rds_instance_integration_cloudwatch_logs",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"vpc_flow_logs_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-dc-an-b-4",
|
||||
"Name": "D3.DC.An.B.4",
|
||||
"Description": "Access to critical systems by third parties is monitored for unauthorized or unusual activity.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-dc-an-b-4",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Detective Controls (DC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"elbv2_logging_enabled",
|
||||
"elb_logging_enabled",
|
||||
"opensearch_service_domains_cloudwatch_logging_enabled",
|
||||
"rds_instance_integration_cloudwatch_logs",
|
||||
"redshift_cluster_audit_logging",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"vpc_flow_logs_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-dc-an-b-5",
|
||||
"Name": "D3.DC.An.B.5",
|
||||
"Description": "Elevated privileges are monitored.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-dc-an-b-5",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Detective Controls (DC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-dc-ev-b-1",
|
||||
"Name": "D3.DC.Ev.B.1",
|
||||
"Description": "A normal network activity baseline is established.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-dc-ev-b-1",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Detective Controls (DC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"elbv2_logging_enabled",
|
||||
"elb_logging_enabled",
|
||||
"redshift_cluster_audit_logging",
|
||||
"vpc_flow_logs_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-dc-ev-b-2",
|
||||
"Name": "D3.DC.Ev.B.2",
|
||||
"Description": "Mechanisms (e.g., antivirus alerts, log event alerts) are in place to alert management to potential attacks.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-dc-ev-b-2",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Detective Controls (DC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-dc-ev-b-3",
|
||||
"Name": "D3.DC.Ev.B.3",
|
||||
"Description": "Processes are in place to monitor for the presence of unauthorized users, devices, connections, and software.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-dc-ev-b-3",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Detective Controls (DC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"guardduty_is_enabled",
|
||||
"securityhub_enabled",
|
||||
"vpc_flow_logs_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-dc-th-b-1",
|
||||
"Name": "D3.DC.Th.B.1",
|
||||
"Description": "Independent testing (including penetration testing and vulnerability scanning) is conducted according to the risk assessment for external-facing systems and the internal network.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-dc-th-b-1",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Detective Controls (DC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_is_enabled",
|
||||
"securityhub_enabled",
|
||||
"ssm_managed_compliant_patching"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-1",
|
||||
"Name": "D3.PC.Am.B.1",
|
||||
"Description": "Employee access is granted to systems and confidential data based on job responsibilities and the principles of least privilege.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-1",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_instance_profile_attached",
|
||||
"iam_policy_attached_only_to_group_or_roles",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges",
|
||||
"iam_no_root_access_key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-10",
|
||||
"Name": "D3.PC.Am.B.10",
|
||||
"Description": "Production and non-production environments are segregated to prevent unauthorized access or changes to information assets. (*N/A if no production environment exists at the institution or the institution's third party.)",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-10",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_networkacl_allow_ingress_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-12",
|
||||
"Name": "D3.PC.Am.B.12",
|
||||
"Description": "All passwords are encrypted in storage and in transit.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-12",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_client_certificate_enabled",
|
||||
"ec2_ebs_volume_encryption",
|
||||
"ec2_ebs_default_encryption",
|
||||
"efs_encryption_at_rest_enabled",
|
||||
"opensearch_service_domains_encryption_at_rest_enabled",
|
||||
"opensearch_service_domains_node_to_node_encryption_enabled",
|
||||
"rds_instance_storage_encrypted",
|
||||
"redshift_cluster_audit_logging",
|
||||
"s3_bucket_default_encryption",
|
||||
"s3_bucket_secure_transport_policy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-13",
|
||||
"Name": "D3.PC.Am.B.13",
|
||||
"Description": "Confidential data is encrypted when transmitted across public or untrusted networks (e.g., Internet).",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-13",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_client_certificate_enabled",
|
||||
"elbv2_insecure_ssl_ciphers",
|
||||
"elb_ssl_listeners",
|
||||
"s3_bucket_secure_transport_policy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-15",
|
||||
"Name": "D3.PC.Am.B.15",
|
||||
"Description": "Remote access to critical systems by employees, contractors, and third parties uses encrypted connections and multifactor authentication.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-15",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_client_certificate_enabled",
|
||||
"iam_root_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled",
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"s3_bucket_secure_transport_policy"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-16",
|
||||
"Name": "D3.PC.Am.B.16",
|
||||
"Description": "Administrative, physical, or technical controls are in place to prevent users without administrative responsibilities from installing unauthorized software.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-16",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-2",
|
||||
"Name": "D3.PC.Am.B.2",
|
||||
"Description": "Employee access to systems and confidential data provides for separation of duties.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-2",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-3",
|
||||
"Name": "D3.PC.Am.B.3",
|
||||
"Description": "Elevated privileges (e.g., administrator privileges) are limited and tightly controlled (e.g., assigned to individuals, not shared, and require stronger password controls",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-3",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges",
|
||||
"iam_root_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled",
|
||||
"iam_no_root_access_key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-6",
|
||||
"Name": "D3.PC.Am.B.6",
|
||||
"Description": "Identification and authentication are required and managed for access to systems, applications, and hardware.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-6",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_password_policy_minimum_length_14",
|
||||
"iam_password_policy_lowercase",
|
||||
"iam_password_policy_number",
|
||||
"iam_password_policy_number",
|
||||
"iam_password_policy_symbol",
|
||||
"iam_password_policy_uppercase",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges",
|
||||
"iam_root_hardware_mfa_enabled",
|
||||
"iam_root_mfa_enabled",
|
||||
"iam_rotate_access_key_90_days",
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_user_mfa_enabled_console_access",
|
||||
"iam_disable_90_days_credentials"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-7",
|
||||
"Name": "D3.PC.Am.B.7",
|
||||
"Description": "Access controls include password complexity and limits to password attempts and reuse.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-7",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_password_policy_minimum_length_14",
|
||||
"iam_password_policy_lowercase",
|
||||
"iam_password_policy_number",
|
||||
"iam_password_policy_number",
|
||||
"iam_password_policy_symbol",
|
||||
"iam_password_policy_uppercase"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-am-b-8",
|
||||
"Name": "D3.PC.Am.B.8",
|
||||
"Description": "All default passwords and unnecessary default accounts are changed before system implementation.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-am-b-8",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"iam_no_root_access_key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-im-b-1",
|
||||
"Name": "D3.PC.Im.B.1",
|
||||
"Description": "Network perimeter defense tools (e.g., border router and firewall) are used.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-im-b-1",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"acm_certificates_expiration_check",
|
||||
"apigateway_waf_acl_attached",
|
||||
"ec2_ebs_public_snapshot",
|
||||
"ec2_instance_public_ip",
|
||||
"elbv2_waf_acl_attached",
|
||||
"emr_cluster_master_nodes_no_public_ip",
|
||||
"awslambda_function_not_publicly_accessible",
|
||||
"awslambda_function_url_public",
|
||||
"rds_instance_no_public_access",
|
||||
"rds_snapshots_public_access",
|
||||
"redshift_cluster_public_access",
|
||||
"s3_bucket_public_access",
|
||||
"s3_bucket_policy_public_write_access",
|
||||
"s3_account_level_public_access_blocks",
|
||||
"s3_bucket_public_access",
|
||||
"sagemaker_notebook_instance_without_direct_internet_access_configured",
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_networkacl_allow_ingress_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-im-b-2",
|
||||
"Name": "D3.PC.Im.B.2",
|
||||
"Description": "Systems that are accessed from the Internet or by external parties are protected by firewalls or other similar devices.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-im-b-2",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_waf_acl_attached",
|
||||
"elbv2_waf_acl_attached",
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_networkacl_allow_ingress_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-im-b-3",
|
||||
"Name": "D3.PC.Im.B.3",
|
||||
"Description": "All ports are monitored.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-im-b-3",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"apigateway_logging_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"elbv2_logging_enabled",
|
||||
"elb_logging_enabled",
|
||||
"vpc_flow_logs_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-im-b-5",
|
||||
"Name": "D3.PC.Im.B.5",
|
||||
"Description": "Systems configurations (for servers, desktops, routers, etc.) follow industry standards and are enforced",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-im-b-5",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_instance_managed_by_ssm",
|
||||
"ssm_managed_compliant_patching",
|
||||
"ssm_managed_compliant_patching"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-im-b-6",
|
||||
"Name": "D3.PC.Im.B.6",
|
||||
"Description": "Ports, functions, protocols and services are prohibited if no longer needed for business purposes.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-im-b-6",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_networkacl_allow_ingress_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-im-b-7",
|
||||
"Name": "D3.PC.Im.B.7",
|
||||
"Description": "Access to make changes to systems configurations (including virtual machines and hypervisors) is controlled and monitored.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-im-b-7",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"iam_policy_attached_only_to_group_or_roles",
|
||||
"iam_aws_attached_policy_no_administrative_privileges",
|
||||
"iam_customer_attached_policy_no_administrative_privileges",
|
||||
"iam_inline_policy_no_administrative_privileges"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d3-pc-se-b-1",
|
||||
"Name": "D3.PC.Se.B.1",
|
||||
"Description": "Developers working for the institution follow secure program coding practices, as part of a system development life cycle (SDLC), that meet industry standards.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d3-pc-se-b1",
|
||||
"Section": "Cybersecurity Controls (Domain 3)",
|
||||
"SubSection": "Preventative Controls (PC)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "d4-c-co-b-2",
|
||||
"Name": "D4.C.Co.B.2",
|
||||
"Description": "The institution ensures that third-party connections are authorized.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d4-c-co-b-2",
|
||||
"Section": "External Dependency Management (Domain 4)",
|
||||
"SubSection": "Connections (C)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"ec2_securitygroup_default_restrict_traffic",
|
||||
"ec2_networkacl_allow_ingress_any_port",
|
||||
"ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22",
|
||||
"ec2_networkacl_allow_ingress_any_port"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d5-dr-de-b-1",
|
||||
"Name": "D5.DR.De.B.1",
|
||||
"Description": "Alert parameters are set for detecting information security incidents that prompt mitigating actions.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d5-dr-de-b-1",
|
||||
"Section": "Cyber Incident Management and Resilience (Domain 5)",
|
||||
"SubSection": "Detection, Response, & Mitigation (DR)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudwatch_changes_to_network_acls_alarm_configured",
|
||||
"cloudwatch_changes_to_network_gateways_alarm_configured",
|
||||
"cloudwatch_changes_to_network_route_tables_alarm_configured",
|
||||
"cloudwatch_changes_to_vpcs_alarm_configured",
|
||||
"guardduty_is_enabled",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d5-dr-de-b-2",
|
||||
"Name": "D5.DR.De.B.2",
|
||||
"Description": "System performance reports contain information that can be used as a risk indicator to detect information security incidents.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d5-dr-de-b-2",
|
||||
"Section": "Cyber Incident Management and Resilience (Domain 5)",
|
||||
"SubSection": "Detection, Response, & Mitigation (DR)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": []
|
||||
},
|
||||
{
|
||||
"Id": "d5-dr-de-b-3",
|
||||
"Name": "D5.DR.De.B.3",
|
||||
"Description": "Tools and processes are in place to detect, alert, and trigger the incident response program.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d5-dr-de-b-3",
|
||||
"Section": "Cyber Incident Management and Resilience (Domain 5)",
|
||||
"SubSection": "Detection, Response, & Mitigation (DR)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_s3_dataevents_read_enabled",
|
||||
"cloudtrail_s3_dataevents_write_enabled",
|
||||
"cloudtrail_multi_region_enabled",
|
||||
"cloudtrail_cloudwatch_logging_enabled",
|
||||
"cloudwatch_changes_to_network_acls_alarm_configured",
|
||||
"cloudwatch_changes_to_network_gateways_alarm_configured",
|
||||
"cloudwatch_changes_to_network_route_tables_alarm_configured",
|
||||
"cloudwatch_changes_to_vpcs_alarm_configured",
|
||||
"elbv2_logging_enabled",
|
||||
"elb_logging_enabled",
|
||||
"guardduty_is_enabled",
|
||||
"rds_instance_integration_cloudwatch_logs",
|
||||
"redshift_cluster_audit_logging",
|
||||
"s3_bucket_server_access_logging_enabled",
|
||||
"securityhub_enabled"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d5-er-es-b-4",
|
||||
"Name": "D5.ER.Es.B.4",
|
||||
"Description": "Incidents are classified, logged and tracked.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d5-er-es-b-4",
|
||||
"Section": "Cyber Incident Management and Resilience (Domain 5)",
|
||||
"SubSection": "Escalation and Reporting (ER)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"guardduty_no_high_severity_findings"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Id": "d5-ir-pl-b-6",
|
||||
"Name": "D5.IR.Pl.B.6",
|
||||
"Description": "The institution plans to use business continuity, disaster recovery, and data backup programs to recover operations following an incident.",
|
||||
"Attributes": [
|
||||
{
|
||||
"ItemId": "d5-ir-pl-b-6",
|
||||
"Section": "Cyber Incident Management and Resilience (Domain 5)",
|
||||
"SubSection": "Incident Resilience Planning & Strategy (IR)",
|
||||
"Service": "aws"
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"dynamodb_tables_pitr_enabled",
|
||||
"elbv2_deletion_protection",
|
||||
"rds_instance_enhanced_monitoring_enabled",
|
||||
"rds_instance_backup_enabled",
|
||||
"rds_instance_deletion_protection",
|
||||
"rds_instance_multi_az",
|
||||
"rds_instance_backup_enabled",
|
||||
"s3_bucket_object_versioning"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||