Initial policies and method for creating policy definition.

This adds some initial example policies:

- One for region restrictions
- One for service restrictions

Note that the MS ARM team has said that region restrictions may be
controlled by ARM, so that policy might prove unnecessary. The
parameters list for the service restrictions is stubbed for now, pending
the full list.

I also added an internal method for adding policy definitions to a
management group. This method is agnostic about what tier of management
group the policy is being defined at. It requires that a dictionary
representing the properties section of a valid Azure JSON policy
definition be passed as an argument.
This commit is contained in:
dandds 2019-12-13 16:32:46 -05:00
parent 7dbdeb3ae7
commit b61956080e
8 changed files with 309 additions and 87 deletions

View File

@ -30,6 +30,7 @@ azure-graphrbac = "*"
msrestazure = "*" msrestazure = "*"
azure-mgmt-authorization = "*" azure-mgmt-authorization = "*"
azure-mgmt-managementgroups = "*" azure-mgmt-managementgroups = "*"
azure-mgmt-resource = "*"
[dev-packages] [dev-packages]
bandit = "*" bandit = "*"

213
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "c2b19c436646705ea3bf4df8c35c2833083f048da37fc619e66f7236153607c5" "sha256": "dc6d11d395668b3e1ae047bec87eac86848348a4d322e00fc9f9837a301a072c"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -25,10 +25,10 @@
}, },
"alembic": { "alembic": {
"hashes": [ "hashes": [
"sha256:49277bb7242192bbb9eac58fed4fe02ec6c3a2a4b4345d2171197459266482b2" "sha256:3b0cb1948833e062f4048992fbc97ecfaaaac24aaa0d83a1202a99fb58af8c6d"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.3.1" "version": "==1.3.2"
}, },
"amqp": { "amqp": {
"hashes": [ "hashes": [
@ -39,11 +39,11 @@
}, },
"apache-libcloud": { "apache-libcloud": {
"hashes": [ "hashes": [
"sha256:9bc5cd5c32151bb7a04a7c7de0be9b4a4b8271e348ac91dd79eaaeeae627115f", "sha256:294d17774618dfb0896b14e69cdc3721850ec44dba81e7f91e701e75235a6eb1",
"sha256:fcc165f2cc2db9a379c6d3a17b3beb9081bb64ba5c0bf7bbb58da864810092f0" "sha256:29ee7d13b9b12d1335e752a489c01eed0c270940147f418cfff89ab66faf1305"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.6.1" "version": "==2.7.0"
}, },
"azure-common": { "azure-common": {
"hashes": [ "hashes": [
@ -76,6 +76,14 @@
"index": "pypi", "index": "pypi",
"version": "==0.2.0" "version": "==0.2.0"
}, },
"azure-mgmt-resource": {
"hashes": [
"sha256:20b3394e4dc76fbd9459723cb8c0300fb18a8c32100076f023b5470426b9f104",
"sha256:eaea8b5d05495d1b74220052275d46b6bed93b59245bcaa747279a52e41c3bdf"
],
"index": "pypi",
"version": "==7.0.0"
},
"azure-mgmt-subscription": { "azure-mgmt-subscription": {
"hashes": [ "hashes": [
"sha256:504b4c42ba859070c3c50637ec07ca36aca600e613fcccaa398db22822fe21f1", "sha256:504b4c42ba859070c3c50637ec07ca36aca600e613fcccaa398db22822fe21f1",
@ -117,11 +125,11 @@
}, },
"celery": { "celery": {
"hashes": [ "hashes": [
"sha256:65f4d67fc1037edacecbf39fcf956da68b984cf2a6d89bd73a8a5a80e35e3dd7", "sha256:7c544f37a84a5eadc44cab1aa8c9580dff94636bb81978cdf9bf8012d9ea7d8f",
"sha256:8a59d80235b876881d9893751f2a87936165fc1347efee66095620b3cadf533b" "sha256:d3363bb5df72d74420986a435449f3c3979285941dff57d5d97ecba352a0e3e2"
], ],
"index": "pypi", "index": "pypi",
"version": "==4.4.0rc4" "version": "==4.4.0"
}, },
"certifi": { "certifi": {
"hashes": [ "hashes": [
@ -208,6 +216,15 @@
], ],
"version": "==2.8" "version": "==2.8"
}, },
"enum34": {
"hashes": [
"sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850",
"sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a",
"sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79",
"sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"
],
"version": "==1.1.6"
},
"flask": { "flask": {
"hashes": [ "hashes": [
"sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52", "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
@ -256,10 +273,11 @@
}, },
"importlib-metadata": { "importlib-metadata": {
"hashes": [ "hashes": [
"sha256:b044f07694ef14a6683b097ba56bd081dbc7cdc7c7fe46011e499dfecc082f21", "sha256:073a852570f92da5f744a3472af1b61e28e9f78ccf0c9117658dc32b15de7b45",
"sha256:e6ac600a142cf2db707b1998382cc7fc3b02befb7273876e01b8ad10b9652742" "sha256:d95141fbfa7ef2ec65cfd945e2af7e5a6ddbd7c8d9a25e66ff3be8e3daf9f60f"
], ],
"version": "==1.1.0" "markers": "python_version < '3.8'",
"version": "==1.3.0"
}, },
"isodate": { "isodate": {
"hashes": [ "hashes": [
@ -284,10 +302,10 @@
}, },
"kombu": { "kombu": {
"hashes": [ "hashes": [
"sha256:1760b54b1d15a547c9a26d3598a1c8cdaf2436386ac1f5561934bc8a3cbbbd86", "sha256:2a9e7adff14d046c9996752b2c48b6d9185d0b992106d5160e1a179907a5d4ac",
"sha256:e7465aa85a1db889116819f08c5de29520d2fa103324dcdca5e90af345f01771" "sha256:67b32ccb6fea030f8799f8fd50dd08e03a4b99464ebc4952d71d8747b1a52ad1"
], ],
"version": "==4.6.6" "version": "==4.6.7"
}, },
"lockfile": { "lockfile": {
"hashes": [ "hashes": [
@ -338,10 +356,10 @@
}, },
"more-itertools": { "more-itertools": {
"hashes": [ "hashes": [
"sha256:53ff73f186307d9c8ef17a9600309154a6ae27f25579e80af4db8f047ba14bc2", "sha256:b84b238cce0d9adad5ed87e745778d20a3f8487d0f0cb8b8a586816c7496458d",
"sha256:a0ea684c39bc4315ba7aae406596ef191fd84f873d2d2751f84d64e81a7a2d45" "sha256:c833ef592a0324bcc6a60e48440da07645063c453880c9477ceb22490aec1564"
], ],
"version": "==8.0.0" "version": "==8.0.2"
}, },
"msrest": { "msrest": {
"hashes": [ "hashes": [
@ -514,10 +532,18 @@
}, },
"sqlalchemy": { "sqlalchemy": {
"hashes": [ "hashes": [
"sha256:afa5541e9dea8ad0014251bc9d56171ca3d8b130c9627c6cb3681cff30be3f8a" "sha256:bfb8f464a5000b567ac1d350b9090cf081180ec1ab4aa87e7bca12dab25320ec"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.3.11" "version": "==1.3.12"
},
"typing": {
"hashes": [
"sha256:91dfe6f3f706ee8cc32d38edbbf304e9b7583fb37108fef38229617f8b3eba23",
"sha256:c8cabb5ab8945cd2f54917be357d134db9cc1eb039e59d1606dc1e60cb1d9d36",
"sha256:f38d83c5a7a7086543a0f649564d661859c5146a85775ab90c0d2f93ffaa9714"
],
"version": "==3.7.4.1"
}, },
"unipath": { "unipath": {
"hashes": [ "hashes": [
@ -677,44 +703,46 @@
}, },
"colorama": { "colorama": {
"hashes": [ "hashes": [
"sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff",
"sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48" "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"
], ],
"version": "==0.4.1" "version": "==0.4.3"
}, },
"coverage": { "coverage": {
"hashes": [ "hashes": [
"sha256:2358e685d0253125da42a48396038d4c7b4cd1448c00bbc4bda0cb8c43c2a870", "sha256:0cd13a6e98c37b510a2d34c8281d5e1a226aaf9b65b7d770ef03c63169965351",
"sha256:25017cf384eeed2e6caf72efd3ec4124e32a8b7a4387600499104387975400c7", "sha256:1a4b6b6a2a3a6612e6361130c2cc3dc4378d8c221752b96167ccbad94b47f3cd",
"sha256:2e2de9423ff8b14303a97eafddd16c479fbcc9a0b8b0be3b7c3843a3e0cf6d69", "sha256:2ee55e6dba516ddf6f484aa83ccabbb0adf45a18892204c23486938d12258cde",
"sha256:324ed908e4e40a6e2451056fe502470ad4e79495cb7a03ecab94e6309c3e117e", "sha256:3be5338a2eb4ef03c57f20917e1d12a1fd10e3853fed060b6d6b677cb3745898",
"sha256:34f865a0cf6255b694a46e4383a7131c61ea72c5b4c4f81d20e522fb1e440b4b", "sha256:44b783b02db03c4777d8cf71bae19eadc171a6f2a96777d916b2c30a1eb3d070",
"sha256:3a2bcc464b60a18f1f7167b95b2773ede93bf3722bfa59e0802717f652b6cc25", "sha256:475bf7c4252af0a56e1abba9606f1e54127cdf122063095c75ab04f6f99cf45e",
"sha256:48d70865266d649b6602e2ba94820d7972ef470d3b72a8fd41a3d17321feed3a", "sha256:47c81ee687eafc2f1db7f03fbe99aab81330565ebc62fb3b61edfc2216a550c8",
"sha256:50cf23523ab3a724c6905d3b60f87fa8250d9bae3995e09f49f63effa2b54f15", "sha256:4a7f8e72b18f2aca288ff02255ce32cc830bc04d993efbc87abf6beddc9e56c0",
"sha256:54c84a68abd8c4c5b71878b35eb85321df41f3d144c78181867d5b026ec74994", "sha256:50197163a22fd17f79086e087a787883b3ec9280a509807daf158dfc2a7ded02",
"sha256:5b59d661ee7f3200aedd7b71882b7927ea7ed522df75e3853f316a79ad872a2e", "sha256:56b13000acf891f700f5067512b804d1ec8c301d627486c678b903859d07f798",
"sha256:5ffb39624bc573177888a21fb301ccee46838c600b27d58c3e9dae495f44d34a", "sha256:79388ae29c896299b3567965dbcd93255f175c17c6c7bca38614d12718c47466",
"sha256:699b3072b7f0e69ed175a88fa8b2ec7eefc4f34d490c54ed9a52feff21a15fdc", "sha256:79fd5d3d62238c4f583b75d48d53cdae759fe04d4fb18fe8b371d88ad2b6f8be",
"sha256:79ef4a2bb862110bd585174e551a783bee5c3aa461734a2ac7429193be357589", "sha256:7fe3e2fde2bf1d7ce25ebcd2d3de3650b8d60d9a73ce6dcef36e20191291613d",
"sha256:8210a6f93c4a8c6d460b402e20e38399529b99200c3318542faf6a520c9b6a5c", "sha256:81042a24f67b96e4287774014fa27220d8a4d91af1043389e4d73892efc89ac6",
"sha256:8d30c10cfd0a6fdf0a2d5023de00ef7b329cd6ead2310c9e53eab79c209acb70", "sha256:81326f1095c53111f8afc95da281e1414185f4a538609a77ca50bdfa39a6c207",
"sha256:97ac79ff28f2cda6ac00a803ee582b965951755f61ab43377482bfba450b619a", "sha256:8873dc0d8f42142ea9f20c27bbdc485190fff93823c6795be661703369e5877d",
"sha256:9fe4aacacff9028ed167db108bf013510654f148d83c4857fed61d2ce0588bf2", "sha256:88d2cbcb0a112f47eef71eb95460b6995da18e6f8ca50c264585abc2c473154b",
"sha256:a5b6395d5957d638f8b1870561607e3c39b1a236ea6cff9eafe5b9bb1db913f2", "sha256:91f2491aeab9599956c45a77c5666d323efdec790bfe23fcceafcd91105d585a",
"sha256:ab32c5fad6905986a7e34e3acf01180a69bb60c2aa7331815b46e51c776a1943", "sha256:979daa8655ae5a51e8e7a24e7d34e250ae8309fd9719490df92cbb2fe2b0422b",
"sha256:ad67f0cfdfecbd49b9da46a7e488e6dc32a69388740b85c36a4ef4b33082cbad", "sha256:9c871b006c878a890c6e44a5b2f3c6291335324b298c904dc0402ee92ee1f0be",
"sha256:aedad67c30326a1af324f45833a40b97180664912deb29942459ddbe9fa0ce19", "sha256:a6d092545e5af53e960465f652e00efbf5357adad177b2630d63978d85e46a72",
"sha256:b077cd0e70f41366ac1f9d09275258fa1906758a5d4f31cacc18b10dfcf90784", "sha256:b5ed7837b923d1d71c4f587ae1539ccd96bfd6be9788f507dbe94dab5febbb5d",
"sha256:b8ea210810d3c14aec7561f8fe0d3eec582d1088100aaa0bb8153d53d867d20f", "sha256:ba259f68250f16d2444cbbfaddaa0bb20e1560a4fdaad50bece25c199e6af864",
"sha256:bf572722326ce6704e863447a070039a827072b7179352570859be899b9e6551", "sha256:be1d89614c6b6c36d7578496dc8625123bda2ff44f224cf8b1c45b810ee7383f",
"sha256:c0df57e189dacd2606cae6386acf127d01d85b2bf49acd9a65543b5d6c359ddc", "sha256:c1b030a79749aa8d1f1486885040114ee56933b15ccfc90049ba266e4aa2139f",
"sha256:d523e75f2a8a0b4a6a8be1287c0e0e3a561b8832b05ddd987d4cd7c62f3ad3bc", "sha256:c95bb147fab76f2ecde332d972d8f4138b8f2daee6c466af4ff3b4f29bd4c19e",
"sha256:e10593c60c5f0bfd8b241bf9f27ef2191a3005b73dde8ada0424f642543a1e59", "sha256:d52c1c2d7e856cecc05aa0526453cb14574f821b7f413cc279b9514750d795c1",
"sha256:e9128444c83bc260aea988bf1ca6278a33ba730955bf94720468c656b61353eb", "sha256:d609a6d564ad3d327e9509846c2c47f170456344521462b469e5cb39e48ba31c",
"sha256:f7162f2e3711f3a08a8a741f92e1f63afd58d0713177979f2cf9723dd50161cf" "sha256:e1bad043c12fb58e8c7d92b3d7f2f49977dcb80a08a6d1e7a5114a11bf819fca",
"sha256:e5a675f6829c53c87d79117a8eb656cc4a5f8918185a32fc93ba09778e90f6db",
"sha256:fec32646b98baf4a22fdceb08703965bd16dea09051fbeb31a04b5b6e72b846c"
], ],
"version": "==5.0b1" "version": "==5.0"
}, },
"decorator": { "decorator": {
"hashes": [ "hashes": [
@ -747,10 +775,10 @@
}, },
"faker": { "faker": {
"hashes": [ "hashes": [
"sha256:48c03580720e0b46538d528b1296e4e5b24a809dcaf33a7dddec719489a9edb8", "sha256:202ad3b2ec16ae7c51c02904fb838831f8d2899e61bf18db1e91a5a582feab11",
"sha256:6327c665c0d8721280b3036d9c9e851c60092bc1f30c8394cc433f8723e2bda5" "sha256:92c84a10bec81217d9cb554ee12b3838c8986ce0b5d45f72f769da22e4bb5432"
], ],
"version": "==2.0.4" "version": "==3.0.0"
}, },
"flask": { "flask": {
"hashes": [ "hashes": [
@ -791,25 +819,26 @@
}, },
"importlib-metadata": { "importlib-metadata": {
"hashes": [ "hashes": [
"sha256:b044f07694ef14a6683b097ba56bd081dbc7cdc7c7fe46011e499dfecc082f21", "sha256:073a852570f92da5f744a3472af1b61e28e9f78ccf0c9117658dc32b15de7b45",
"sha256:e6ac600a142cf2db707b1998382cc7fc3b02befb7273876e01b8ad10b9652742" "sha256:d95141fbfa7ef2ec65cfd945e2af7e5a6ddbd7c8d9a25e66ff3be8e3daf9f60f"
], ],
"version": "==1.1.0" "markers": "python_version < '3.8'",
"version": "==1.3.0"
}, },
"ipdb": { "ipdb": {
"hashes": [ "hashes": [
"sha256:473fdd798a099765f093231a8b1fabfa95b0b682fce12de0c74b61a4b4d8ee57" "sha256:5d9a4a0e3b7027a158fc6f2929934341045b9c3b0b86ed5d7e84e409653f72fd"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.12.2" "version": "==0.12.3"
}, },
"ipython": { "ipython": {
"hashes": [ "hashes": [
"sha256:c66c7e27239855828a764b1e8fc72c24a6f4498a2637572094a78c5551fb9d51", "sha256:190a279bd3d4fc585a611e9358a88f1048cc57fd688254a86f9461889ee152a6",
"sha256:f186b01b36609e0c5d0de27c7ef8e80c990c70478f8c880863004b3489a9030e" "sha256:762d79a62b6aa96b04971e920543f558dfbeedc0468b899303c080c8068d4ac2"
], ],
"index": "pypi", "index": "pypi",
"version": "==7.10.1" "version": "==7.10.2"
}, },
"ipython-genutils": { "ipython-genutils": {
"hashes": [ "hashes": [
@ -914,10 +943,10 @@
}, },
"more-itertools": { "more-itertools": {
"hashes": [ "hashes": [
"sha256:53ff73f186307d9c8ef17a9600309154a6ae27f25579e80af4db8f047ba14bc2", "sha256:b84b238cce0d9adad5ed87e745778d20a3f8487d0f0cb8b8a586816c7496458d",
"sha256:a0ea684c39bc4315ba7aae406596ef191fd84f873d2d2751f84d64e81a7a2d45" "sha256:c833ef592a0324bcc6a60e48440da07645063c453880c9477ceb22490aec1564"
], ],
"version": "==8.0.0" "version": "==8.0.2"
}, },
"mypy": { "mypy": {
"hashes": [ "hashes": [
@ -948,10 +977,10 @@
}, },
"parso": { "parso": {
"hashes": [ "hashes": [
"sha256:63854233e1fadb5da97f2744b6b24346d2750b85965e7e399bec1620232797dc", "sha256:55cf25df1a35fd88b878715874d2c4dc1ad3f0eebd1e0266a67e1f55efccfbe1",
"sha256:666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c" "sha256:5c1f7791de6bd5dbbeac8db0ef5594b36799de198b3f7f7014643b0c5536b9d3"
], ],
"version": "==0.5.1" "version": "==0.5.2"
}, },
"pathspec": { "pathspec": {
"hashes": [ "hashes": [
@ -1063,11 +1092,11 @@
}, },
"pytest-mock": { "pytest-mock": {
"hashes": [ "hashes": [
"sha256:96a0cebc66e09930be2a15b03333d90b59584d3fb011924f81c14b50ee0afbba", "sha256:67e414b3caef7bff6fc6bd83b22b5bc39147e4493f483c2679bc9d4dc485a94d",
"sha256:e5381be2608e49547f5e47633c5f81241ebf6206d17ce516a7a18d5a917e3859" "sha256:e24a911ec96773022ebcc7030059b57cd3480b56d4f5d19b7c370ec635e6aed5"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.12.1" "version": "==1.13.0"
}, },
"pytest-watch": { "pytest-watch": {
"hashes": [ "hashes": [
@ -1102,21 +1131,31 @@
}, },
"regex": { "regex": {
"hashes": [ "hashes": [
"sha256:15454b37c5a278f46f7aa2d9339bda450c300617ca2fca6558d05d870245edc7", "sha256:3d2d5952639615815a5dde7431265fc45b58106ca687ea16b60699c6946bfe02",
"sha256:1ad40708c255943a227e778b022c6497c129ad614bb7a2a2f916e12e8a359ee7", "sha256:3dbd8333fd2ebd50977ac8747385a73aa1f546eb6b16fcd83d274470fe11f243",
"sha256:5e00f65cc507d13ab4dfa92c1232d004fa202c1d43a32a13940ab8a5afe2fb96", "sha256:40b7d1291a56897927e08bb973f8c186c2feb14c7f708bfe7aaee09483e85a20",
"sha256:604dc563a02a74d70ae1f55208ddc9bfb6d9f470f6d1a5054c4bd5ae58744ab1", "sha256:517a827c4c9bcd4a158f48970258c17a52bdd133300c93affe8b5e9ae7b4675d",
"sha256:720e34a539a76a1fedcebe4397290604cc2bdf6f81eca44adb9fb2ea071c0c69", "sha256:580e849ba64d7d82019c52d766b1f42cd8a398622278e8f89126800d7e5d52ea",
"sha256:7caf47e4a9ac6ef08cabd3442cc4ca3386db141fb3c8b2a7e202d0470028e910", "sha256:719978a9145d59fc78509ea1d1bb74243f93583ef2a34dcc5623cf8118ae9726",
"sha256:7faf534c1841c09d8fefa60ccde7b9903c9b528853ecf41628689793290ca143", "sha256:75cf3796f89f75f83207a5c6a6e14eaf57e0369ef0ffff8e22bf36bbcfa0f1de",
"sha256:b4e0406d822aa4993ac45072a584d57aa4931cf8288b5455bbf30c1d59dbad59", "sha256:77396cf80be8b2a35db863cca4c1a902d88ceeb183adab328b81184e71a5eafe",
"sha256:c31eaf28c6fe75ea329add0022efeed249e37861c19681960f99bbc7db981fb2", "sha256:77a3799152951d6d14ae5720ca162c97c64f85d4755da585418eac216b736cad",
"sha256:c7393597191fc2043c744db021643549061e12abe0b3ff5c429d806de7b93b66", "sha256:91235c98283d2bddf1a588f0fbc2da8afa37959294bbd18b76297bdf316ba4d6",
"sha256:d2b302f8cdd82c8f48e9de749d1d17f85ce9a0f082880b9a4859f66b07037dc6", "sha256:99981ccc110b55d3bc2f5140167b8515c57f782ccdd0cd85d8217e1af1f1c632",
"sha256:e3d8dd0ec0ea280cf89026b0898971f5750a7bd92cb62c51af5a52abd020054a", "sha256:a07f449fef6b8159080fd0be0e15b593ea55c2760f6340076fecc2845eac6c42",
"sha256:ec032cbfed59bd5a4b8eab943c310acfaaa81394e14f44454ad5c9eba4f24a74" "sha256:a35d1353ec805cea8a74bc5e141cc20083f2ade3d68bd92aa8b54115f08b902b",
"sha256:a70eb00ea3c18f68102cb125677812f66cacecc5a6187fa48eaef898b3ba45e5",
"sha256:aaffd68c4c1ed891366d5c390081f4bf6337595e76a157baf453603d8e53fbcb",
"sha256:ad9e3c7260809c0d1ded100269f78ea0217c0704f1eaaf40a382008461848b45",
"sha256:ba442ecf7df4c1657db237fa284719d95a8298bbac0056a73aca4e8a127f2968",
"sha256:bbddddfc768052abe88d02010c1f00c7dcd88430b775239fcc44ad2b1c9285b1",
"sha256:c203c9ee755e9656d0af8fab82754d5a664ebaf707b3f883c7eff6a3dd5151cf",
"sha256:c630f23491d0810767d3523b18b9c1e67c35319e298ed7e1a05dea0402ebd424",
"sha256:ccb78a4bf24b150e5b62cf5edff1e5f0b700064407dd0f03a5db7ff8451ee437",
"sha256:e865bc508e316a3a09d36c8621596e6599a203bc54f1cd41020a127ccdac468a",
"sha256:f8e3ca4669f6b09fdcbb3da71b358c7976f203d3e86b9e1be47790ed8915085e"
], ],
"version": "==2019.11.1" "version": "==2019.12.9"
}, },
"requests": { "requests": {
"hashes": [ "hashes": [

View File

@ -401,6 +401,7 @@ REMOTE_ROOT_ROLE_DEF_ID = "/providers/Microsoft.Authorization/roleDefinitions/00
class AzureSDKProvider(object): class AzureSDKProvider(object):
def __init__(self): def __init__(self):
from azure.mgmt import subscription, authorization, managementgroups from azure.mgmt import subscription, authorization, managementgroups
from azure.mgmt.resource import policy
import azure.graphrbac as graphrbac import azure.graphrbac as graphrbac
import azure.common.credentials as credentials import azure.common.credentials as credentials
from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD
@ -410,6 +411,7 @@ class AzureSDKProvider(object):
self.managementgroups = managementgroups self.managementgroups = managementgroups
self.graphrbac = graphrbac self.graphrbac = graphrbac
self.credentials = credentials self.credentials = credentials
self.policy = policy
# may change to a JEDI cloud # may change to a JEDI cloud
self.cloud = AZURE_PUBLIC_CLOUD self.cloud = AZURE_PUBLIC_CLOUD
@ -561,6 +563,51 @@ class AzureCloudProvider(CloudProviderInterface):
# but we just don't have a valid ID # but we just don't have a valid ID
pass pass
AZURE_MANAGEMENT_API = "https://management.azure.com"
def _create_policy_definition(
self, credentials, subscription_id, management_group_id, properties,
):
"""
Requires credentials that have AZURE_MANAGEMENT_API
specified as the resource. The Service Principal
specified in the credentials must have the "Resource
Policy Contributor" role assigned with a scope at least
as high as the management group specified by
management_group_id.
Arguments:
credentials -- ServicePrincipalCredentials
subscription_id -- str, ID of the subscription (just the UUID, not the path)
management_group_id -- str, ID of the management group (just the UUID, not the path)
properties -- dictionary, the "properties" section of a valid Azure policy definition document
Returns:
azure.mgmt.resource.policy.[api version].models.PolicyDefinition: the PolicyDefinition object provided to Azure
Raises:
TBD
"""
# TODO: which subscription would this be?
client = self.sdk.policy.PolicyClient(credentials, subscription_id)
definition = client.policy_definitions.models.PolicyDefinition(
policy_type=properties.get("policyType"),
mode=properties.get("mode"),
display_name=properties.get("displayName"),
description=properties.get("description"),
policy_rule=properties.get("policyRule"),
parameters=properties.get("parameters"),
)
name = properties.get("displayName")
return client.policy_definitions.create_or_update_at_management_group(
policy_definition_name=name,
parameters=definition,
management_group_id=management_group_id,
)
def _get_management_service_principal(self): def _get_management_service_principal(self):
# we really should be using graph.microsoft.com, but i'm getting # we really should be using graph.microsoft.com, but i'm getting
# "expired token" errors for that # "expired token" errors for that

12
atst/domain/csp/policy.py Normal file
View File

@ -0,0 +1,12 @@
class AzurePolicyManager:
def __init__(self, static_policy_location):
self._static_policy_location = static_policy_location
def portfolio_definitions():
pass
def application_definitions():
pass
def environment_definitions():
pass

View File

@ -0,0 +1,40 @@
{
"definitionPoint": "portfolio-parent",
"policyDefinition": {
"properties": {
"displayName": "Allowed resource types",
"policyType": "Custom",
"mode": "Indexed",
"description": "This policy enables you to specify the resource types that your organization can deploy.",
"parameters": {
"listOfResourceTypesAllowed": {
"type": "Array",
"metadata": {
"description": "The list of resource types that can be deployed.",
"displayName": "Allowed resource types",
"strongType": "resourceTypes"
}
}
},
"policyRule": {
"if": {
"not": {
"field": "type",
"in": "[parameters('listOfResourceTypesAllowed')]"
}
},
"then": {
"effect": "deny"
}
}
},
"type": "Microsoft.Authorization/policyDefinitions"
},
"parameters": {
"listOfResourceTypesAllowed": {
"value": [
"Microsoft.Cache"
]
}
}
}

View File

@ -0,0 +1,51 @@
{
"definitionPoint": "portfolio-parent",
"policyDefinition": {
"properties": {
"displayName": "Custom - Region Restriction",
"policyType": "Custom",
"mode": "Indexed",
"parameters": {
"listOfAllowedLocations": {
"type": "Array",
"metadata": {
"displayName": "Allowed locations",
"description": "The list of locations that can be specified when deploying resources.",
"strongType": "location"
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "location",
"notIn": "[parameters('listOfAllowedLocations')]"
},
{
"field": "location",
"notEquals": "global"
},
{
"field": "type",
"notEquals": "Microsoft.AzureActiveDirectory/b2cDirectories"
}
]
},
"then": {
"effect": "Deny"
}
}
},
"type": "Microsoft.Authorization/policyDefinitions"
},
"parameters": {
"listOfAllowedLocations": {
"value": [
"eastus",
"southcentralus",
"westus"
]
}
}
}

View File

@ -90,3 +90,28 @@ def test_create_atat_admin_user_succeeds(mock_azure: AzureCloudProvider):
result = mock_azure.create_atat_admin_user(AUTH_CREDENTIALS, environment_id) result = mock_azure.create_atat_admin_user(AUTH_CREDENTIALS, environment_id)
assert result.get("csp_user_id") == csp_user_id assert result.get("csp_user_id") == csp_user_id
def test_create_policy_definition_succeeds(mock_azure: AzureCloudProvider):
subscription_id = str(uuid4())
management_group_id = str(uuid4())
properties = {
"policyType": "test",
"displayName": "test policy",
}
result = mock_azure._create_policy_definition(
AUTH_CREDENTIALS, subscription_id, management_group_id, properties
)
azure_sdk_method = (
mock_azure.sdk.policy.PolicyClient.return_value.policy_definitions.create_or_update_at_management_group
)
mock_policy_definition = (
mock_azure.sdk.policy.PolicyClient.return_value.policy_definitions.models.PolicyDefinition()
)
assert azure_sdk_method.called
azure_sdk_method.assert_called_with(
management_group_id=management_group_id,
policy_definition_name=properties.get("displayName"),
parameters=mock_policy_definition,
)

View File

@ -46,6 +46,12 @@ def mock_credentials():
return Mock(spec=credentials) return Mock(spec=credentials)
def mock_policy():
from azure.mgmt.resource import policy
return Mock(spec=policy)
class MockAzureSDK(object): class MockAzureSDK(object):
def __init__(self): def __init__(self):
from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD
@ -55,6 +61,7 @@ class MockAzureSDK(object):
self.managementgroups = mock_managementgroups() self.managementgroups = mock_managementgroups()
self.graphrbac = mock_graphrbac() self.graphrbac = mock_graphrbac()
self.credentials = mock_credentials() self.credentials = mock_credentials()
self.policy = mock_policy()
# may change to a JEDI cloud # may change to a JEDI cloud
self.cloud = AZURE_PUBLIC_CLOUD self.cloud = AZURE_PUBLIC_CLOUD