From 0bbcaae2e9712fd62c7348337a94ec42b1653fee Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Tue, 21 Sep 2021 10:53:28 +0530 Subject: [PATCH 01/33] Modifying Readme --- .vs/AzTS-Samples/v16/.suo | Bin 0 -> 11264 bytes .vs/ProjectSettings.json | 3 +++ .vs/slnx.sqlite | Bin 0 -> 90112 bytes README.md | 3 ++- 4 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .vs/AzTS-Samples/v16/.suo create mode 100644 .vs/ProjectSettings.json create mode 100644 .vs/slnx.sqlite diff --git a/.vs/AzTS-Samples/v16/.suo b/.vs/AzTS-Samples/v16/.suo new file mode 100644 index 0000000000000000000000000000000000000000..3127bb3e78f5d3dc4cdc0e3ed2be1e8e344b30a0 GIT binary patch literal 11264 zcmeHNOK)366h3Y#P~N2wAQT8FLS5k0P8`P$qH2?rheSx#ypYJ|+Sf_kJZ!}dB_IS_ zR`3_tu_1yb3#9&ovSSNNenUmW_szXyk0*YNuhXUxKGF4^nL9IQ&THnJGx_7rxxaq= zb?|So;If>Sdk1IbQKLO(l;t^*$5Ch7y@P`TeqtHLKAa#9+>jFfsxl2>SV~8JK6# zvSSWxQYQXK(0&S!EB&vcueR%FQ2y5>AS^!{&PUs3Up7C5_tSV@z(X4N?JVBpfsS>f8+kI+w{KAI_0n1`F;uYm#sGQJIj4Iehy5*<0;7o z{1Fen#)jd2KzI&t0saU5e)<8V#$kvIqSM8&;{xzjfcIngIu&?A^Rljdu&U&hXH@Ah zA^o4z=%e?Z4&Bw~SMVFUpUU5)m$w7o%Yz^GKGv~`dZl(U6|j=3Ok-8_j|=LzzN*Ox z{wH-`uX6_TlG3ek=4Ist`e?m{6_l`!BCr+}_BvKQS|kDbX_NG+UHLzNzTbsYnD}PF z0diqY@nZxu?<$#;u(}Vxp%Ut4`2;<<+F&)8fuH>3oUZt(FFZ>KuJ{*#y#&dS7v&H) z$AkYdo=?;%SNt5O@y~<%`B2uMV{SjBeO_UsZyxY|1R7cb<-XE{U8Mz_2lOkv#7$sZ zC%AwPTK~GiPfMxF6eK}80L7nt(+-VWXd z{~1GQ|G!;d{f&DCV+cZP{Cm){oRUJ&v-vOZcg_Ds`)j0s7W8fbE8}2OH=EfWSM*K< z{M@S+LUL^SDcu6(y8$gPDOpq@b#o=*!0?p<|9RF1+UKT!v=^;^_L*$f*~hH2e3a)u z=j+4qa=_NVK-0L-1euVl(8IFKqQ?A0&>E_qdZnR%q~Jx=_%^?_Dl^v5`;V#F_W5&N z>HjwD!N-IVbzPl8*neZprw}(m zudCgg{)*oJ+TmXY4*DB&kO1H0gAJn*=x44-$G=GP_5`2aVKf*WhH;)XdY~2LBA4LT zBqS*#>bKqO^d*i0J{$OLU%nl@)a_hbUUB=)Z+`wI>Ue*7`uASOce`G@Kkc9w9`-t( zde{qo+7ZXs=O|x6)fswSzcZp19qa3E(ZQja_H08hZT4LEvmP@f7X^<#N1}}781kQf z^fV%g6sYEIr&lQr{czPo3XD7UDHtCHia#gs_ zRTLRJOkJ8^m`sjlCKHoiC0FyKiBUfl_fv@^rWnh|vzf6}d^|Ur%#2T@a=G-x*WrMy z^8i{{>qCZLdDlQNZE+EG^5#Px1m<77R%>4}$FO{#fN{?(BBdZQ4Q`F-GcZ!txowg6 zzyb2$-9xKj9DZK4g4$ycjeYtC6m-7#(uDN$Ki&JEjC(ZyjywM|i#=>nhSa{c39Z%n zjv*rxrq|l+9VPze{R?gVs6aX1;m=Xc+08sB8NVI>MaciiG3S3&{K=de<=`T>M*I7J z=YMSZFT-PD?wyfmtDKj~UV8 z17XgyT-yoTbAkEKZtb7BdYyl3hCjGv@UaSC-A}Yz5A!edAIMKv`Wdln{C1u@xaU|! zj$=*bf2j>Y1{{N$0P>$P-WO{gH0g4viMb-}kj){pauXiZ8oX`$j%7(QhsN3sZvj8$ zsqdui@6GDum5z_5;khxdUO~>G2#()6w2Edk)Z1|XRHNOM|Bd?(?|;lJ(BWGjMj6aW zGXlw}SfY+U1N`)#dDrTSpZys(5N!SH+ke;g-?jW7Ci`y_ngt5d;kTdv>n;Dsy^Hp! NJeLUh$6oV?{{g}??M?sy literal 0 HcmV?d00001 diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000..f8b4888 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..7d2d80afbb29346f3d8fad9982544f9046bef620 GIT binary patch literal 90112 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 T0T2KI5C8!X009s Date: Wed, 22 Sep 2021 21:02:14 +0530 Subject: [PATCH 02/33] Initial Commit --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c15efe..9abfae4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # AzTS-Samples -AzTS-Samples \ No newline at end of file +AzTS-Samples + From 92540e8725bd6e98c61839cd4c51acea6e550ef9 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Fri, 24 Sep 2021 01:57:55 +0530 Subject: [PATCH 03/33] Adding AzTS_Extended Solution --- AzTS_Extended/AzTS_Extended.csproj | 58 +++++ AzTS_Extended/AzTS_Extended.sln | 25 ++ ...v_GetAllSubscriptionWorkItemsToProcess.kql | 7 + .../Configurations/appsettings.Local.json | 238 ++++++++++++++++++ AzTS_Extended/Configurations/appsettings.json | 165 ++++++++++++ .../FeatureNameControlEvaluatorExt.cs | 68 +++++ AzTS_Extended/Processor.cs | 40 +++ AzTS_Extended/Properties/launchSettings.json | 24 ++ AzTS_Extended/Startup.cs | 167 ++++++++++++ AzTS_Extended/host.json | 22 ++ AzTS_Extended/local.settings.json | 9 + 11 files changed, 823 insertions(+) create mode 100644 AzTS_Extended/AzTS_Extended.csproj create mode 100644 AzTS_Extended/AzTS_Extended.sln create mode 100644 AzTS_Extended/Configurations/LAQueries/Inv_GetAllSubscriptionWorkItemsToProcess.kql create mode 100644 AzTS_Extended/Configurations/appsettings.Local.json create mode 100644 AzTS_Extended/Configurations/appsettings.json create mode 100644 AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs create mode 100644 AzTS_Extended/Processor.cs create mode 100644 AzTS_Extended/Properties/launchSettings.json create mode 100644 AzTS_Extended/Startup.cs create mode 100644 AzTS_Extended/host.json create mode 100644 AzTS_Extended/local.settings.json diff --git a/AzTS_Extended/AzTS_Extended.csproj b/AzTS_Extended/AzTS_Extended.csproj new file mode 100644 index 0000000..3022c0a --- /dev/null +++ b/AzTS_Extended/AzTS_Extended.csproj @@ -0,0 +1,58 @@ + + + Library + true + Start-AzSKTSScan + ./nupkg + netcoreapp3.1 + v3 + AnyCPU;x64 + + + + netcoreapp3.1 + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + Never + + + Always + + + \ No newline at end of file diff --git a/AzTS_Extended/AzTS_Extended.sln b/AzTS_Extended/AzTS_Extended.sln new file mode 100644 index 0000000..43d5acd --- /dev/null +++ b/AzTS_Extended/AzTS_Extended.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31624.102 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzTS_Extended", "AzTS_Extended.csproj", "{E5C68E6E-D6AE-4748-9C25-D101E5341630}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E5C68E6E-D6AE-4748-9C25-D101E5341630}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5C68E6E-D6AE-4748-9C25-D101E5341630}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5C68E6E-D6AE-4748-9C25-D101E5341630}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5C68E6E-D6AE-4748-9C25-D101E5341630}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {861BB5CF-3C37-4336-8888-4371C14738BB} + EndGlobalSection +EndGlobal diff --git a/AzTS_Extended/Configurations/LAQueries/Inv_GetAllSubscriptionWorkItemsToProcess.kql b/AzTS_Extended/Configurations/LAQueries/Inv_GetAllSubscriptionWorkItemsToProcess.kql new file mode 100644 index 0000000..9529085 --- /dev/null +++ b/AzTS_Extended/Configurations/LAQueries/Inv_GetAllSubscriptionWorkItemsToProcess.kql @@ -0,0 +1,7 @@ +AzSK_SubInventory_CL +| where TimeGenerated > ago(2d) +| where JobId_d == toint(format_datetime(now(), 'yyyyMMdd')) +| where State_s != 'Disabled' +| summarize arg_max(TimeGenerated, *) by SubscriptionId +| project SubscriptionId +| distinct SubscriptionId \ No newline at end of file diff --git a/AzTS_Extended/Configurations/appsettings.Local.json b/AzTS_Extended/Configurations/appsettings.Local.json new file mode 100644 index 0000000..5e63194 --- /dev/null +++ b/AzTS_Extended/Configurations/appsettings.Local.json @@ -0,0 +1,238 @@ +{ + "AppMetadata": { + "AppCurrentVersion": "1.0.0" + }, + "AuthNSettings": { + "ScannerIdentityConnectionString": "", + "InternalIdentityConnectionString": "" + }, + "AuthzSettings": { + "IsPIMEnabled": true, + "IsRGPIMEnabled": false, + "MaxDegreeOfParallelismForSubPIMProcess": 50, + "MaxDegreeOfParallelismForRGPIMProcess": 4 + }, + "AzureStorageSettings": { + "ResourceId": "", + "ContainerName": "azskatsscanresult", + "QueueName": "subjobqueue", + "FileNames": { + "SubscriptionMetadata": "{0}/Subscriptions/SubMetaData/{1}_SubMetaData.json", + "SubscriptionRBAC": "{0}/Subscriptions/RBAC/{1}_RBAC.json", + "ResourceInventory": "{0}/Subscriptions/ResourceInventory/{1}_ResourceInventory.json", + "PolicyAssessments": "{0}/Subscriptions/SSAssessmentDetails/{1}_SSAssessmentDetails.json", + "ControlEvaluation": "{0}/Subscriptions/ControlResults/{1}_ControlResults.json" + } + }, + "HttpClientConfig": { + "MaxRetries": 3, + "RetryHttpStatusCodes": [ 429, 408, 502, 504 ], + "RetryStepInSecs": 6 + }, + "LAConfigurations": { + "WorkspaceId": "", + "ResourceId": "", + "LATypes": { + "PolicySummary": "AzSK_PolicySummaryInfo", + "SubscriptionRBAC": "AzSK_RBAC", + "ADGraph": "AzSK_AADObjectInv", + "PolicyAssignments": "AzSK_PolicyAssignmentsInv", + "PolicyAssessments": "AzSK_SSAssessmentInv", + "PolicyStates": "AzSK_PolicyStateResults", + "ControlEvaluation": "AzSK_ControlResults", + "ProcessedEvent": "AzSK_ProcessedSubscriptions", + "Exceptions": "AzSK_RTExceptions", + "PerformanceMetrics": "AzSK_PerformanceMetrics", + "ResourceInventory": "AzSK_ResourceInvInfo" + }, + "QueryFiles": { + + }, + "Functions": { + + }, + "BatchSize": 500 + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Trace", + "System.Net.Http": "None" + } + }, + "WebJobConfigurations": { + "ForceFetch": false, + "MaxExecutionTimeInUTCHour": 14 + }, + "FeatureManagement": { + "All": true, + "ManagementGroups": true, + "ADGraph": true, + "Subscriptions": true, + "PolicyDefinitions": true, + "BaselineControls": true, + "ControlScanException": true, + "ScanExternalControl": true, + "ControlResultRetention": true + }, + "ManagementGroupConfigurations": { + "ManagementGroupId": "", + "HierarchyTraverseLimit": 7 + }, + "GraphConfigurations": { + "BatchSize": 1000 + }, + "WorkItemProcessorSettings": { + "BatchSize": 30000, + "MinThreshold": 1, + "MessageMaxTimeToLive": "03:00:00", + "CacheClearingOn": true, + "VerificationResultRetentionPeriodInDays": 7 + }, + "RepositorySettings": { + "SQLDatabase": { + "ResourceEvaluationLimit": 5000 + }, + "Storage": { + "StorageContainerFetchLimit": 5000 + }, + "VirtualMachineScaleSet": { + "VirtualMachineInstancesLimit": 50 + }, + "LogicApps": { + "LogicAppsReturnObjectsLimit": 50000 + } + }, + "AzureSQLSettings": { + "IsFeatureEnabled": false, + "UseKeyVault": false, + "ConnectionStringForGetRequest": "FILL", + "ConnectionStringForUploadRequest": "FILL", + "ConnectionStringKeyVaultUriForGetRequest": "FILL", + "ConnectionStringKeyVaultUriForUploadRequest": "FILL", + "CommandExecutionConfig": [ + { + "FeatureId": "ControlEvaluationScheduledScanSQLWrite", + "Name": "[dbo].[LastKnownScanResultRawSS]", + "ExecutionType": "SqlBulkCopy", + "BatchSize": 0 + }, + { + "FeatureId": "RoleAssignmentDetailsSQLWrite", + "Name": "[dbo].[RoleAssignmentDetailsRawSS]", + "ExecutionType": "SqlBulkCopy", + "BatchSize": 0 + }, + { + "FeatureId": "ControlEvaluationAdhocScanSQLWrite", + "Name": "[dbo].[LastKnownScanResultRawAS]", + "ExecutionType": "SqlBulkCopy", + "BatchSize": 0 + }, + { + "FeatureId": "ControlExceptionSQLRead", + "Name": "[dbo].[GetControlScanExceptionBySubscriptionId]", + "Parameters": [ + { + "Name": "@SubscriptionId", + "SqlDbType": "UNIQUEIDENTIFIER" + }, + { + "Name": "@SubscriptionIntId", + "SqlDbType": "INT", + "IsNullable": true + } + ] + }, + { + "FeatureId": "BulkExceptionSQLRead", + "Name": "[dbo].[GetBulkExceptionBySubscriptionId]", + "Parameters": [ + { + "Name": "@SubscriptionId", + "SqlDbType": "UNIQUEIDENTIFIER" + }, + { + "Name": "@SubscriptionIntId", + "SqlDbType": "INT", + "IsNullable": true + } + ] + }, + { + "FeatureId": "ControlEvaluationSQLRead", + "Name": "[dbo].[GetControlScanResultBySubscriptionId]", + "Parameters": [ + { + "Name": "@SubscriptionId", + "SqlDbType": "UNIQUEIDENTIFIER" + }, + { + "Name": "@SubscriptionIntId", + "SqlDbType": "INT", + "IsNullable": true + } + ] + }, + { + "FeatureId": "SubscriptionJobIdMappingScheduledScanSQLWrite", + "Name": "[dbo].[UpdateSubscriptionJobIdMappingSS]", + "Parameters": [ + { + "Name": "@SubscriptionId", + "SqlDbType": "UNIQUEIDENTIFIER" + }, + { + "Name": "@SubscriptionIntId", + "SqlDbType": "INT", + "IsNullable": true + }, + { + "Name": "@JobId", + "SqlDbType": "BIGINT" + } + ] + }, + { + "FeatureId": "SubscriptionJobIdMappingAdhocScanSQLWrite", + "Name": "[dbo].[UpdateSubscriptionJobIdMappingAS]", + "Parameters": [ + { + "Name": "@SubscriptionId", + "SqlDbType": "UNIQUEIDENTIFIER" + }, + { + "Name": "@SubscriptionIntId", + "SqlDbType": "INT", + "IsNullable": true + }, + { + "Name": "@JobId", + "SqlDbType": "BIGINT" + } + ] + }, + { + "FeatureId": "ProcessAdhocScanResultFromRawToMasterSQLWrite", + "Name": "[dbo].[ADFProcessAdhocScanResultFromRawToMaster]", + "Parameters": [ + { + "Name": "@SubscriptionId", + "SqlDbType": "UNIQUEIDENTIFIER" + } + ] + }, + { + "FeatureId": "SubscriptionIntIdSQLRead", + "Name": "[dbo].[GetSubscriptionsFromSubscriptionMaster]", + "Parameters": [ + { + "Name": "@SubscriptionId", + "SqlDbType": "UNIQUEIDENTIFIER", + "IsNullable": true + } + ] + } + ] + } +} \ No newline at end of file diff --git a/AzTS_Extended/Configurations/appsettings.json b/AzTS_Extended/Configurations/appsettings.json new file mode 100644 index 0000000..b0f6d34 --- /dev/null +++ b/AzTS_Extended/Configurations/appsettings.json @@ -0,0 +1,165 @@ +{ + "AppMetadata": { + "AppCurrentVersion": "1.0.0" + }, + "AuthNSettings": { + "ScannerIdentityConnectionString": "", + "InternalIdentityConnectionString": "" + }, + "AuthzSettings": { + "IsPIMEnabled": false, + "IsRGPIMEnabled": false, + "MaxDegreeOfParallelismForSubPIMProcess": 50, + "MaxDegreeOfParallelismForRGPIMProcess": 4 + }, + "AzureStorageSettings": { + "ResourceId": "", + "ContainerName": "azskatsscanresult", + "QueueName": "subjobqueue", + "FileNames": { + "SubscriptionMetadata": "{0}/Subscriptions/SubMetaData/{1}_SubMetaData.json", + "SubscriptionRBAC": "{0}/Subscriptions/RBAC/{1}_RBAC.json", + "ResourceInventory": "{0}/Subscriptions/ResourceInventory/{1}_ResourceInventory.json", + "PolicyAssessments": "{0}/Subscriptions/SSAssessmentDetails/{1}_SSAssessmentDetails.json", + "ControlEvaluation": "{0}/Subscriptions/ControlResults/{1}_ControlResults.json", + "ControlExtensions": "Ext/{0}.ext.json", + "PolicyStates": "{0}/Subscriptions/PolicyStateResults/{1}_PolicyStateResults.json" + }, + "FeatureContainerName": { + "PolicyExtension": "orgpolicy" + } + }, + "EndpointMapping": { + "AzureCloud": { + "AzureManagement": "https://management.azure.com/", + "GraphAPI": "https://graph.microsoft.com", + "AzureADGraphAPI": "https://graph.windows.net", + "LogAnalytics": "https://api.loganalytics.io/", + "LogAnalyticsDataCollector": "https://{0}.ods.opinsights.azure.com", + "ApplicationInsights": "https://management.azure.com", + "ManagementCore": "https://management.core.windows.net/", + "StorageEndpointSuffix": "core.windows.net", + "AzureSQL": "https://database.windows.net/", + "KuduConsole": "https://{0}.scm.azurewebsites.net" + }, + "AzureGovernmentCloud": { + "AzureManagement": "https://management.usgovcloudapi.net/", + "GraphAPI": "https://graph.microsoft.us", + "AzureADGraphAPI": "https://graph.windows.net", + "LogAnalytics": "https://api.loganalytics.us/", + "LogAnalyticsDataCollector": "https://{0}.ods.opinsights.azure.us", + "ApplicationInsights": "https://management.usgovcloudapi.net/", + "ManagementCore": "https://management.core.usgovcloudapi.net/", + "StorageEndpointSuffix": "core.usgovcloudapi.net", + "AzureSQL": "https://database.usgovcloudapi.net/", + "KuduConsole": "https://{0}.scm.azurewebsites.us/" + } + }, + "HttpClientConfig": { + "MaxRetries": 3, + "RetryHttpStatusCodes": [ 429, 408, 502, 504 ], + "RetryStepInSecs": 6 + }, + "LAConfigurations": { + "WorkspaceId": "", + "ResourceId": "", + "LATypes": { + "PolicySummary": "AzSK_PolicySummaryInfo", + "SubscriptionRBAC": "AzSK_RBAC", + "ADGraph": "AzSK_AADObjectInv", + "PolicyAssignments": "AzSK_PolicyAssignmentsInv", + "PolicyAssessments": "AzSK_SSAssessmentInv", + "PolicyStates": "AzSK_PolicyStateResults", + "ControlEvaluation": "AzSK_ControlResults", + "ProcessedEvent": "AzSK_ProcessedSubscriptions", + "Exceptions": "AzSK_RTExceptions", + "PerformanceMetrics": "AzSK_PerformanceMetrics", + "ResourceInventory": "AzSK_ResourceInvInfo", + "SecureScoreAssessmentSummary": "AzSK_SSAssessmentSummaryInv" + }, + "QueryFiles": { + }, + "Functions": { + + }, + "BatchSize": 500 + }, + "ARGConfigurations": { + "QueryFiles": { + "PolicyStateDataForAllAssignments": "Arg_Policy_GetPolicyStatesForAllAssignments.json", + "PolicyStateDataForSelectedAssignments": "Arg_Policy_GetPolicyStatesForSelectedAssignments.json", + "GetASCSecureScore": "Arg_Policy_GetSecureScore.json", + "GetASCSecureScoreControls": "Arg_Policy_GetSecureScoreControls.json" + }, + "PolicyStateSettings": { + "MaxDegreeOfParallelism": 10, + "BatchSize": 100, + "FetchAll": false + }, + "SecureScoreSettings": { + "MaxDegreeOfParallelism": 5, + "BatchSize": 1000, + "FetchAll": true + }, + "MaxRetries": 3, + "QuotaResetsInSecs": 5, + "RetryStatusCodes": [ "TooManyRequests" ] + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Trace", + "System.Net.Http": "None" + } + }, + "WebJobConfigurations": { + "ForceFetch": false, + "MaxExecutionTimeInUTCHour": 14, + "CloudEnvironmentName": "AzureCloud" + }, + "FeatureManagement": { + "All": true, + "ManagementGroups": true, + "ADGraph": true, + "Subscriptions": true, + "PolicyDefinitions": true, + "PolicyStates": false, + "BaselineControls": true, + "ControlScanException": true, + "OrgPolicy": false, + "ScanExternalControl": false, + "ControlResultRetention": false + }, + "ManagementGroupConfigurations": { + "ManagementGroupId": "", + "HierarchyTraverseLimit": 7 + }, + "GraphConfigurations": { + "BatchSize": 1000, + "IsFeatureEnabled": true + }, + "WorkItemProcessorSettings": { + "BatchSize": 30000, + "MinThreshold": 1, + "MessageMaxTimeToLive": "03:00:00", + "CacheClearingOn": true, + "VerificationResultRetentionPeriodInDays": 7 + }, + "RepositorySettings": { + "SQLDatabase": { + "ResourceEvaluationLimit": 5000 + }, + "Storage": { + "StorageContainerFetchLimit": 5000 + }, + "VirtualMachineScaleSet": { + "VirtualMachineInstancesLimit": 50 + }, + "LogicApps": { + "LogicAppsReturnObjectsLimit": 50000 + } + }, + "AzureSQLSettings": { + "IsFeatureEnabled": false + } +} \ No newline at end of file diff --git a/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs b/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs new file mode 100644 index 0000000..0812bb2 --- /dev/null +++ b/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs @@ -0,0 +1,68 @@ +namespace AzTS_Extended.ControlEvaluator +{ + using Microsoft.AzSK.ATS.Extensions.Authorization; + using Microsoft.AzSK.ATS.Extensions.Models; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Models; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Processors.ControlProcessors.ServiceControlEvaluators; + using Newtonsoft.Json.Linq; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + class SubscriptionCoreEvaluatorExt : SubscriptionCoreEvaluator + { + /// + /// Checks the count of classic administrators at subscription scope. + /// .Passed + /// The count of classic administrators does not exceed 2. + /// .Failed + /// More than 2 classic administrators accounts found. + /// .Verify + /// RBAC result not found (sufficient data is not available for evaluation). + /// + /// Control result object. + /// return evaluated control result. + public ControlResult CheckCoAdminCount(ControlResult cr) + { + int noOfClassicAdminsLimit = cr.ControlDetails.ControlSettings?["NoOfClassicAdminsLimit"]?.Value() ?? 2; + string classicAdminAccountsString = "No classic admin accounts found."; + int classicAdminAccountsCount = 0; + + // NOTE: While fetching RBAC result, we make three API calls - PIM, ARM, Classic. We are *not* handling partial result scenario if error occurred while fetching any of these RBAC result. + // If no RBAC is found, mark status as Verify because sufficient data is not available for evaluation. + if (this.RBACList?.Any() == false) + { + cr.VerificationResult = VerificationResultStatus.Verify; + cr.StatusReason = "[Trial] No RBAC result found for this subscription."; + cr.ConsiderForCompliance = false; + return cr; + } + else + { + List classicAdminAccounts = new List(); + classicAdminAccounts = RBACList.AsParallel().Where(rbacItem => rbacItem.RoleName.ToLower().Contains("coadministrator") || rbacItem.RoleName.ToLower().Contains("serviceadministrator")).ToList(); + + // First start with default value, override this if classic admin account is found. + if (classicAdminAccounts != null && classicAdminAccounts.Any()) + { + classicAdminAccountsCount = classicAdminAccounts.Count; + classicAdminAccountsString = string.Join(",", classicAdminAccounts.Select(a => a.ToStringClassicAssignment()).ToList()); + } + + // Start with failed state, mark control as Passed if all required conditions are met + cr.StatusReason = $"[Trial] No. of classic administrators found: [{classicAdminAccountsCount}]. Principal name results based on RBAC inv: [{String.Join(", ", classicAdminAccounts.Select(a => a.PrincipalName))}]"; + cr.VerificationResult = VerificationResultStatus.Failed; + + // Classic admin accounts count does not exceed the limit. + if (classicAdminAccountsCount <= noOfClassicAdminsLimit) + { + cr.VerificationResult = VerificationResultStatus.Passed; + } + } + + return cr; + } + + } +} diff --git a/AzTS_Extended/Processor.cs b/AzTS_Extended/Processor.cs new file mode 100644 index 0000000..1516da4 --- /dev/null +++ b/AzTS_Extended/Processor.cs @@ -0,0 +1,40 @@ +namespace AzTS_Extended +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.IO; + using System.Linq; + using Microsoft.AzSK.ATS.Extensions; + using Microsoft.AzSK.ATS.Extensions.Models; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Models; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Processors; + using Microsoft.Azure.WebJobs; + using Microsoft.Extensions.Logging; + using Newtonsoft.Json; + + public class Processor + { + private SubscriptionItemProcessor _subscriptionItemProcessor; + + public Processor( + SubscriptionItemProcessor subscriptionItemProcessor) + { + _subscriptionItemProcessor = subscriptionItemProcessor; + } + + // This function will get triggered/executed when a new message is written + // on an Azure Queue called queue. + [FunctionName("SubWorkItemProcessor")] + //public void Run([QueueTrigger("%queueTriggerName%")] string workItem, ILogger log) + + public void Run([TimerTrigger("0 */60 0-12 * * *", RunOnStartup = true)] TimerInfo timer, ILogger log) + { + string workItem = "{\"SubscriptionId\":\"\",\"Timestamp\":\"Sun, 01 Mar 2020 14:39:49 GMT\",\"JobId\":20200229,\"RetryCount\":0, \"IsRBACProcessed\": true}"; + var workItemObject = JsonConvert.DeserializeObject(workItem); + workItemObject.IsRBACProcessed = false; + _subscriptionItemProcessor._log = log; + _subscriptionItemProcessor.ProcessSubscriptionItems(workItemObject); + } + } +} \ No newline at end of file diff --git a/AzTS_Extended/Properties/launchSettings.json b/AzTS_Extended/Properties/launchSettings.json new file mode 100644 index 0000000..9bcfd99 --- /dev/null +++ b/AzTS_Extended/Properties/launchSettings.json @@ -0,0 +1,24 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:50023", + "sslPort": 44375 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "AzTS_Extended": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/AzTS_Extended/Startup.cs b/AzTS_Extended/Startup.cs new file mode 100644 index 0000000..afbe36d --- /dev/null +++ b/AzTS_Extended/Startup.cs @@ -0,0 +1,167 @@ +using Microsoft.Azure.Functions.Extensions.DependencyInjection; + +[assembly: FunctionsStartup(typeof(AzTS_Extended.Startup))] + +namespace AzTS_Extended +{ + using System; + using System.IO; + using System.Net.Http; + using Microsoft.AzSK.ATS.EndpointProvider; + using Microsoft.AzSK.ATS.Extensions; + using Microsoft.AzSK.ATS.Extensions.Authentication; + using Microsoft.AzSK.ATS.Extensions.Authorization; + using Microsoft.AzSK.ATS.Extensions.ConfigurationProvider; + using Microsoft.AzSK.ATS.Extensions.EventProcessor; + using Microsoft.AzSK.ATS.Extensions.ExceptionProvider; + using Microsoft.AzSK.ATS.Extensions.Graph; + using Microsoft.AzSK.ATS.Extensions.HttpHelper; + using Microsoft.AzSK.ATS.Extensions.Models; + using Microsoft.AzSK.ATS.Extensions.PollyPolicyHelper; + using Microsoft.AzSK.ATS.Extensions.Storage; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Processors; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Repositories; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Repositories.ResourceRepositories; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Repositories.SubscriptionRespositories; + using Microsoft.AzSK.ATS.WorkItemProcessor.Processors.ControlProcessors; + using Microsoft.AzSK.ATS.WorkItemProcessor.Repositories; + using Microsoft.AzSK.ATS.WorkItemProcessor.Repositories.SubscriptionRespositories; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.FeatureManagement; + using Polly.Registry; + + class Startup : FunctionsStartup + { + private static IPolicyRegistry _policyRegistry; + private IConfiguration _configuration; + + /// + /// Configuration load for function apps. + /// + /// Function config builder instance. + public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder) + { + FunctionsHostBuilderContext context = builder.GetContext(); + + // Get configurations paths + // var azure_root = $"{Environment.GetEnvironmentVariable("HOME")}/site/wwwroot"; + string configurationRootPath = Path.Combine(context.ApplicationRootPath, "Configurations"); + var temp = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); + /*if (!Directory.Exists(azure_root)) + { + azure_root = Directory.GetCurrentDirectory(); + configurationRootPath = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory() + @"\..\..\..\..\Configurations\Extended")); + }*/ + + if (string.IsNullOrWhiteSpace(configurationRootPath)) + { + throw new ArgumentException("App setting not found."); + } + + var laQueryFilesPath = Path.Combine(configurationRootPath, "LAQueries"); + _configuration = builder.ConfigurationBuilder + .AddJsonFile(Path.Combine(configurationRootPath, "appsettings.json"), optional: false, reloadOnChange: true) + .AddJsonFile(Path.Combine(configurationRootPath, $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json"), optional: false, reloadOnChange: true) + .AddKeyPerFile(laQueryFilesPath, true) + .AddEnvironmentVariables() + .Build(); + } + + /// + /// Configure dependencies for application. + /// + /// Functions host builder instance. + public override void Configure(IFunctionsHostBuilder builder) + { + var services = builder.Services; + + // Add configurations from app settings + + // Enable inbuilt services + // services.AddHttpClient(); + services.AddLogging(); + services.AddApplicationInsightsTelemetry(); + services.AddFeatureManagement(_configuration); + + // Configurations settings + // Notes: Configurations read using the options pattern + var webJobConfigurations = _configuration.GetSection(WebJobConfigurations.ConfigName).Get(); + services.Configure(_configuration.GetSection(string.Concat(EndpointMapping.ConfigName, ":", webJobConfigurations.CloudEnvironmentName))); + services.Configure(_configuration.GetSection(LAConfigurations.ConfigName)); + services.Configure(_configuration.GetSection(GraphConfigurations.ConfigName)); + //// Notes: Named options pattern used for mapping configurations with strongly typed properties/classes + services.Configure(_configuration.GetSection(WebJobConfigurations.ConfigName)); + services.Configure(_configuration.GetSection(AzureStorageSettings.ConfigName)); + services.Configure(_configuration.GetSection(AuthNSettings.ConfigName)); + services.Configure(_configuration.GetSection(AuthzSettings.ConfigName)); + services.Configure(_configuration.GetSection(HttpClientConfig.ConfigName)); + services.Configure(_configuration.GetSection(AzureSQLSettings.ConfigName)); + services.Configure(_configuration.GetSection(AzureControlScanExceptionSettings.ConfigName)); + services.Configure(_configuration.GetSection(AADClientAppDetails.ConfigName)); + services.Configure(_configuration.GetSection(AppMetadata.ConfigName)); + + // TODO: Check if this can be added + services.Configure(_configuration.GetSection(RepositorySettings.ConfigName)); + + services.Configure(_configuration.GetSection(RuleEngineSettings.ConfigName)); + + // Notes: Named options pattern used for mapping configurations with strongly typed properties/classes + services.Configure(_configuration.GetSection(WorkItemProcessorSettings.ConfigName)); + + // Helper classes registration + + // services.AddHttpClient().AddPolicyRegistry(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddScoped(); + services.AddSingleton(); + services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); + services.AddSingleton(); + services.AddSingleton(); + + // Repository classes registration + services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddSingleton(); + services.AddScoped(); + // To handle "Scope disposed{no name, Parent=disposed{no name, Parent=disposed{no name}}} is disposed and scoped instances are disposed and no longer available" exception. + // TODO: Replace the timespan as need. eg(Timeout.InfiniteTimeSpan or TimeSpan.FromHours(2) for 2 hrs) + //_policyRegistry = services.AddPolicyRegistry(); + //PolicyHelper.CreateAndRegisterPolicies(_configuration, _policyRegistry); + services.AddHttpClient(HttpClientConfig.HttpClientName).SetHandlerLifetime(TimeSpan.FromHours(2)); + + // .AddPolicyHandler(httpRequestMessage => + //{ + // return _policyRegistry.Get>(PolicyHelper.PolicyName.WaitAndRetryPolicy); + //}); + + + } + } +} \ No newline at end of file diff --git a/AzTS_Extended/host.json b/AzTS_Extended/host.json new file mode 100644 index 0000000..d324292 --- /dev/null +++ b/AzTS_Extended/host.json @@ -0,0 +1,22 @@ +{ + "version": "2.0", + "extensions": { + "queues": { + "visibilityTimeout": "01:00:00" + } + }, + "logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Information", + "System.Net.Http": "None" + }, + "applicationInsights": { + //"samplingExcludedTypes": "Request", + "samplingSettings": { + "isEnabled": false + } + } + }, + "functionTimeout": "00:09:00" +} \ No newline at end of file diff --git a/AzTS_Extended/local.settings.json b/AzTS_Extended/local.settings.json new file mode 100644 index 0000000..326f1f1 --- /dev/null +++ b/AzTS_Extended/local.settings.json @@ -0,0 +1,9 @@ +{ + "IsEncrypted": false, + "Values": { + "ASPNETCORE_ENVIRONMENT": "Local", + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "FUNCTIONS_WORKER_RUNTIME": "dotnet", + "APPINSIGHTS_INSTRUMENTATIONKEY": "" + } +} \ No newline at end of file From 9963772173cb2a74bef90b87d6e83c7f1c2b4852 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Fri, 24 Sep 2021 02:06:39 +0530 Subject: [PATCH 04/33] Adding External ControlConfig template --- AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json diff --git a/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json b/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json new file mode 100644 index 0000000..0405eb6 --- /dev/null +++ b/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json @@ -0,0 +1,7 @@ +{ + "FeatureName": "", + "Reference": "", + "IsMaintenanceMode": false, + "Controls": [ + ] +} \ No newline at end of file From 69dceef53766e783658224e16f023b1f0422a727 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Fri, 24 Sep 2021 02:13:25 +0530 Subject: [PATCH 05/33] Removing package reference --- AzTS_Extended/AzTS_Extended.csproj | 5 ----- 1 file changed, 5 deletions(-) diff --git a/AzTS_Extended/AzTS_Extended.csproj b/AzTS_Extended/AzTS_Extended.csproj index 3022c0a..752b9cc 100644 --- a/AzTS_Extended/AzTS_Extended.csproj +++ b/AzTS_Extended/AzTS_Extended.csproj @@ -17,11 +17,6 @@ - - - - - Always From 7bdeb486d395ca9d3d901b001803f5b0c16d5bbb Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Fri, 24 Sep 2021 11:31:30 +0530 Subject: [PATCH 06/33] Updating FeatureNameControlEvaluatorExt.cs --- .../FeatureNameControlEvaluatorExt.cs | 55 +------------------ 1 file changed, 2 insertions(+), 53 deletions(-) diff --git a/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs b/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs index 0812bb2..f777a5b 100644 --- a/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs +++ b/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs @@ -10,59 +10,8 @@ using System.Linq; using System.Text; - class SubscriptionCoreEvaluatorExt : SubscriptionCoreEvaluator + class FeatureNameEvaluatorExt : FeatureNameEvaluator { - /// - /// Checks the count of classic administrators at subscription scope. - /// .Passed - /// The count of classic administrators does not exceed 2. - /// .Failed - /// More than 2 classic administrators accounts found. - /// .Verify - /// RBAC result not found (sufficient data is not available for evaluation). - /// - /// Control result object. - /// return evaluated control result. - public ControlResult CheckCoAdminCount(ControlResult cr) - { - int noOfClassicAdminsLimit = cr.ControlDetails.ControlSettings?["NoOfClassicAdminsLimit"]?.Value() ?? 2; - string classicAdminAccountsString = "No classic admin accounts found."; - int classicAdminAccountsCount = 0; - - // NOTE: While fetching RBAC result, we make three API calls - PIM, ARM, Classic. We are *not* handling partial result scenario if error occurred while fetching any of these RBAC result. - // If no RBAC is found, mark status as Verify because sufficient data is not available for evaluation. - if (this.RBACList?.Any() == false) - { - cr.VerificationResult = VerificationResultStatus.Verify; - cr.StatusReason = "[Trial] No RBAC result found for this subscription."; - cr.ConsiderForCompliance = false; - return cr; - } - else - { - List classicAdminAccounts = new List(); - classicAdminAccounts = RBACList.AsParallel().Where(rbacItem => rbacItem.RoleName.ToLower().Contains("coadministrator") || rbacItem.RoleName.ToLower().Contains("serviceadministrator")).ToList(); - - // First start with default value, override this if classic admin account is found. - if (classicAdminAccounts != null && classicAdminAccounts.Any()) - { - classicAdminAccountsCount = classicAdminAccounts.Count; - classicAdminAccountsString = string.Join(",", classicAdminAccounts.Select(a => a.ToStringClassicAssignment()).ToList()); - } - - // Start with failed state, mark control as Passed if all required conditions are met - cr.StatusReason = $"[Trial] No. of classic administrators found: [{classicAdminAccountsCount}]. Principal name results based on RBAC inv: [{String.Join(", ", classicAdminAccounts.Select(a => a.PrincipalName))}]"; - cr.VerificationResult = VerificationResultStatus.Failed; - - // Classic admin accounts count does not exceed the limit. - if (classicAdminAccountsCount <= noOfClassicAdminsLimit) - { - cr.VerificationResult = VerificationResultStatus.Passed; - } - } - - return cr; - } - + } } From ae821610051b27801e4de858fbd9995d146f0928 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Fri, 24 Sep 2021 11:33:45 +0530 Subject: [PATCH 07/33] Delete .vs directory --- .vs/AzTS-Samples/v16/.suo | Bin 11264 -> 0 bytes .vs/ProjectSettings.json | 3 --- .vs/slnx.sqlite | Bin 90112 -> 0 bytes 3 files changed, 3 deletions(-) delete mode 100644 .vs/AzTS-Samples/v16/.suo delete mode 100644 .vs/ProjectSettings.json delete mode 100644 .vs/slnx.sqlite diff --git a/.vs/AzTS-Samples/v16/.suo b/.vs/AzTS-Samples/v16/.suo deleted file mode 100644 index 3127bb3e78f5d3dc4cdc0e3ed2be1e8e344b30a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11264 zcmeHNOK)366h3Y#P~N2wAQT8FLS5k0P8`P$qH2?rheSx#ypYJ|+Sf_kJZ!}dB_IS_ zR`3_tu_1yb3#9&ovSSNNenUmW_szXyk0*YNuhXUxKGF4^nL9IQ&THnJGx_7rxxaq= zb?|So;If>Sdk1IbQKLO(l;t^*$5Ch7y@P`TeqtHLKAa#9+>jFfsxl2>SV~8JK6# zvSSWxQYQXK(0&S!EB&vcueR%FQ2y5>AS^!{&PUs3Up7C5_tSV@z(X4N?JVBpfsS>f8+kI+w{KAI_0n1`F;uYm#sGQJIj4Iehy5*<0;7o z{1Fen#)jd2KzI&t0saU5e)<8V#$kvIqSM8&;{xzjfcIngIu&?A^Rljdu&U&hXH@Ah zA^o4z=%e?Z4&Bw~SMVFUpUU5)m$w7o%Yz^GKGv~`dZl(U6|j=3Ok-8_j|=LzzN*Ox z{wH-`uX6_TlG3ek=4Ist`e?m{6_l`!BCr+}_BvKQS|kDbX_NG+UHLzNzTbsYnD}PF z0diqY@nZxu?<$#;u(}Vxp%Ut4`2;<<+F&)8fuH>3oUZt(FFZ>KuJ{*#y#&dS7v&H) z$AkYdo=?;%SNt5O@y~<%`B2uMV{SjBeO_UsZyxY|1R7cb<-XE{U8Mz_2lOkv#7$sZ zC%AwPTK~GiPfMxF6eK}80L7nt(+-VWXd z{~1GQ|G!;d{f&DCV+cZP{Cm){oRUJ&v-vOZcg_Ds`)j0s7W8fbE8}2OH=EfWSM*K< z{M@S+LUL^SDcu6(y8$gPDOpq@b#o=*!0?p<|9RF1+UKT!v=^;^_L*$f*~hH2e3a)u z=j+4qa=_NVK-0L-1euVl(8IFKqQ?A0&>E_qdZnR%q~Jx=_%^?_Dl^v5`;V#F_W5&N z>HjwD!N-IVbzPl8*neZprw}(m zudCgg{)*oJ+TmXY4*DB&kO1H0gAJn*=x44-$G=GP_5`2aVKf*WhH;)XdY~2LBA4LT zBqS*#>bKqO^d*i0J{$OLU%nl@)a_hbUUB=)Z+`wI>Ue*7`uASOce`G@Kkc9w9`-t( zde{qo+7ZXs=O|x6)fswSzcZp19qa3E(ZQja_H08hZT4LEvmP@f7X^<#N1}}781kQf z^fV%g6sYEIr&lQr{czPo3XD7UDHtCHia#gs_ zRTLRJOkJ8^m`sjlCKHoiC0FyKiBUfl_fv@^rWnh|vzf6}d^|Ur%#2T@a=G-x*WrMy z^8i{{>qCZLdDlQNZE+EG^5#Px1m<77R%>4}$FO{#fN{?(BBdZQ4Q`F-GcZ!txowg6 zzyb2$-9xKj9DZK4g4$ycjeYtC6m-7#(uDN$Ki&JEjC(ZyjywM|i#=>nhSa{c39Z%n zjv*rxrq|l+9VPze{R?gVs6aX1;m=Xc+08sB8NVI>MaciiG3S3&{K=de<=`T>M*I7J z=YMSZFT-PD?wyfmtDKj~UV8 z17XgyT-yoTbAkEKZtb7BdYyl3hCjGv@UaSC-A}Yz5A!edAIMKv`Wdln{C1u@xaU|! zj$=*bf2j>Y1{{N$0P>$P-WO{gH0g4viMb-}kj){pauXiZ8oX`$j%7(QhsN3sZvj8$ zsqdui@6GDum5z_5;khxdUO~>G2#()6w2Edk)Z1|XRHNOM|Bd?(?|;lJ(BWGjMj6aW zGXlw}SfY+U1N`)#dDrTSpZys(5N!SH+ke;g-?jW7Ci`y_ngt5d;kTdv>n;Dsy^Hp! NJeLUh$6oV?{{g}??M?sy diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json deleted file mode 100644 index f8b4888..0000000 --- a/.vs/ProjectSettings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "CurrentProjectSetting": null -} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite deleted file mode 100644 index 7d2d80afbb29346f3d8fad9982544f9046bef620..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90112 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 T0T2KI5C8!X009s Date: Mon, 27 Sep 2021 10:31:59 +0530 Subject: [PATCH 08/33] Modifying Extension CE --- .../ControlEvaluator/FeatureNameControlEvaluatorExt.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs b/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs index f777a5b..a3d4331 100644 --- a/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs +++ b/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs @@ -10,7 +10,7 @@ using System.Linq; using System.Text; - class FeatureNameEvaluatorExt : FeatureNameEvaluator + class FeatureNameEvaluatorExt : BaseControlEvaluator { } From b07a7e32dd67e56aa922b8d0da62cf67008c25f0 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Fri, 8 Oct 2021 15:51:59 +0530 Subject: [PATCH 09/33] Adding Control JSON template --- .../ControlConfigurationExt/FeatureNameExt.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json b/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json index 0405eb6..10b365b 100644 --- a/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json +++ b/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json @@ -3,5 +3,13 @@ "Reference": "", "IsMaintenanceMode": false, "Controls": [ + { + "ControlID": "", + "Id": "", + "Automated": "Yes", + "MethodName": "", + "DisplayName": "", + "Enabled": + } ] -} \ No newline at end of file +} From 0d88a772913370300741b4818093180c5ebf89b7 Mon Sep 17 00:00:00 2001 From: Vishal H Date: Fri, 22 Oct 2021 15:35:41 +0530 Subject: [PATCH 10/33] Fixed syntax issues --- AzTS_Extended/AzTS_Extended.csproj | 7 +- .../Configurations/appsettings.Local.json | 238 ------------------ .../FeatureNameExt.json | 2 +- AzTS_Extended/Processor.cs | 5 +- AzTS_Extended/Startup.cs | 1 - AzTS_Extended/local.settings.json | 15 +- 6 files changed, 17 insertions(+), 251 deletions(-) delete mode 100644 AzTS_Extended/Configurations/appsettings.Local.json diff --git a/AzTS_Extended/AzTS_Extended.csproj b/AzTS_Extended/AzTS_Extended.csproj index 752b9cc..53a5541 100644 --- a/AzTS_Extended/AzTS_Extended.csproj +++ b/AzTS_Extended/AzTS_Extended.csproj @@ -17,6 +17,10 @@ + + + + Always @@ -30,9 +34,6 @@ Always - - Always - Always diff --git a/AzTS_Extended/Configurations/appsettings.Local.json b/AzTS_Extended/Configurations/appsettings.Local.json deleted file mode 100644 index 5e63194..0000000 --- a/AzTS_Extended/Configurations/appsettings.Local.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "AppMetadata": { - "AppCurrentVersion": "1.0.0" - }, - "AuthNSettings": { - "ScannerIdentityConnectionString": "", - "InternalIdentityConnectionString": "" - }, - "AuthzSettings": { - "IsPIMEnabled": true, - "IsRGPIMEnabled": false, - "MaxDegreeOfParallelismForSubPIMProcess": 50, - "MaxDegreeOfParallelismForRGPIMProcess": 4 - }, - "AzureStorageSettings": { - "ResourceId": "", - "ContainerName": "azskatsscanresult", - "QueueName": "subjobqueue", - "FileNames": { - "SubscriptionMetadata": "{0}/Subscriptions/SubMetaData/{1}_SubMetaData.json", - "SubscriptionRBAC": "{0}/Subscriptions/RBAC/{1}_RBAC.json", - "ResourceInventory": "{0}/Subscriptions/ResourceInventory/{1}_ResourceInventory.json", - "PolicyAssessments": "{0}/Subscriptions/SSAssessmentDetails/{1}_SSAssessmentDetails.json", - "ControlEvaluation": "{0}/Subscriptions/ControlResults/{1}_ControlResults.json" - } - }, - "HttpClientConfig": { - "MaxRetries": 3, - "RetryHttpStatusCodes": [ 429, 408, 502, 504 ], - "RetryStepInSecs": 6 - }, - "LAConfigurations": { - "WorkspaceId": "", - "ResourceId": "", - "LATypes": { - "PolicySummary": "AzSK_PolicySummaryInfo", - "SubscriptionRBAC": "AzSK_RBAC", - "ADGraph": "AzSK_AADObjectInv", - "PolicyAssignments": "AzSK_PolicyAssignmentsInv", - "PolicyAssessments": "AzSK_SSAssessmentInv", - "PolicyStates": "AzSK_PolicyStateResults", - "ControlEvaluation": "AzSK_ControlResults", - "ProcessedEvent": "AzSK_ProcessedSubscriptions", - "Exceptions": "AzSK_RTExceptions", - "PerformanceMetrics": "AzSK_PerformanceMetrics", - "ResourceInventory": "AzSK_ResourceInvInfo" - }, - "QueryFiles": { - - }, - "Functions": { - - }, - "BatchSize": 500 - }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Trace", - "System.Net.Http": "None" - } - }, - "WebJobConfigurations": { - "ForceFetch": false, - "MaxExecutionTimeInUTCHour": 14 - }, - "FeatureManagement": { - "All": true, - "ManagementGroups": true, - "ADGraph": true, - "Subscriptions": true, - "PolicyDefinitions": true, - "BaselineControls": true, - "ControlScanException": true, - "ScanExternalControl": true, - "ControlResultRetention": true - }, - "ManagementGroupConfigurations": { - "ManagementGroupId": "", - "HierarchyTraverseLimit": 7 - }, - "GraphConfigurations": { - "BatchSize": 1000 - }, - "WorkItemProcessorSettings": { - "BatchSize": 30000, - "MinThreshold": 1, - "MessageMaxTimeToLive": "03:00:00", - "CacheClearingOn": true, - "VerificationResultRetentionPeriodInDays": 7 - }, - "RepositorySettings": { - "SQLDatabase": { - "ResourceEvaluationLimit": 5000 - }, - "Storage": { - "StorageContainerFetchLimit": 5000 - }, - "VirtualMachineScaleSet": { - "VirtualMachineInstancesLimit": 50 - }, - "LogicApps": { - "LogicAppsReturnObjectsLimit": 50000 - } - }, - "AzureSQLSettings": { - "IsFeatureEnabled": false, - "UseKeyVault": false, - "ConnectionStringForGetRequest": "FILL", - "ConnectionStringForUploadRequest": "FILL", - "ConnectionStringKeyVaultUriForGetRequest": "FILL", - "ConnectionStringKeyVaultUriForUploadRequest": "FILL", - "CommandExecutionConfig": [ - { - "FeatureId": "ControlEvaluationScheduledScanSQLWrite", - "Name": "[dbo].[LastKnownScanResultRawSS]", - "ExecutionType": "SqlBulkCopy", - "BatchSize": 0 - }, - { - "FeatureId": "RoleAssignmentDetailsSQLWrite", - "Name": "[dbo].[RoleAssignmentDetailsRawSS]", - "ExecutionType": "SqlBulkCopy", - "BatchSize": 0 - }, - { - "FeatureId": "ControlEvaluationAdhocScanSQLWrite", - "Name": "[dbo].[LastKnownScanResultRawAS]", - "ExecutionType": "SqlBulkCopy", - "BatchSize": 0 - }, - { - "FeatureId": "ControlExceptionSQLRead", - "Name": "[dbo].[GetControlScanExceptionBySubscriptionId]", - "Parameters": [ - { - "Name": "@SubscriptionId", - "SqlDbType": "UNIQUEIDENTIFIER" - }, - { - "Name": "@SubscriptionIntId", - "SqlDbType": "INT", - "IsNullable": true - } - ] - }, - { - "FeatureId": "BulkExceptionSQLRead", - "Name": "[dbo].[GetBulkExceptionBySubscriptionId]", - "Parameters": [ - { - "Name": "@SubscriptionId", - "SqlDbType": "UNIQUEIDENTIFIER" - }, - { - "Name": "@SubscriptionIntId", - "SqlDbType": "INT", - "IsNullable": true - } - ] - }, - { - "FeatureId": "ControlEvaluationSQLRead", - "Name": "[dbo].[GetControlScanResultBySubscriptionId]", - "Parameters": [ - { - "Name": "@SubscriptionId", - "SqlDbType": "UNIQUEIDENTIFIER" - }, - { - "Name": "@SubscriptionIntId", - "SqlDbType": "INT", - "IsNullable": true - } - ] - }, - { - "FeatureId": "SubscriptionJobIdMappingScheduledScanSQLWrite", - "Name": "[dbo].[UpdateSubscriptionJobIdMappingSS]", - "Parameters": [ - { - "Name": "@SubscriptionId", - "SqlDbType": "UNIQUEIDENTIFIER" - }, - { - "Name": "@SubscriptionIntId", - "SqlDbType": "INT", - "IsNullable": true - }, - { - "Name": "@JobId", - "SqlDbType": "BIGINT" - } - ] - }, - { - "FeatureId": "SubscriptionJobIdMappingAdhocScanSQLWrite", - "Name": "[dbo].[UpdateSubscriptionJobIdMappingAS]", - "Parameters": [ - { - "Name": "@SubscriptionId", - "SqlDbType": "UNIQUEIDENTIFIER" - }, - { - "Name": "@SubscriptionIntId", - "SqlDbType": "INT", - "IsNullable": true - }, - { - "Name": "@JobId", - "SqlDbType": "BIGINT" - } - ] - }, - { - "FeatureId": "ProcessAdhocScanResultFromRawToMasterSQLWrite", - "Name": "[dbo].[ADFProcessAdhocScanResultFromRawToMaster]", - "Parameters": [ - { - "Name": "@SubscriptionId", - "SqlDbType": "UNIQUEIDENTIFIER" - } - ] - }, - { - "FeatureId": "SubscriptionIntIdSQLRead", - "Name": "[dbo].[GetSubscriptionsFromSubscriptionMaster]", - "Parameters": [ - { - "Name": "@SubscriptionId", - "SqlDbType": "UNIQUEIDENTIFIER", - "IsNullable": true - } - ] - } - ] - } -} \ No newline at end of file diff --git a/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json b/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json index 10b365b..5314cc6 100644 --- a/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json +++ b/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json @@ -9,7 +9,7 @@ "Automated": "Yes", "MethodName": "", "DisplayName": "", - "Enabled": + "Enabled": false } ] } diff --git a/AzTS_Extended/Processor.cs b/AzTS_Extended/Processor.cs index 1516da4..c10af6b 100644 --- a/AzTS_Extended/Processor.cs +++ b/AzTS_Extended/Processor.cs @@ -30,11 +30,12 @@ public Processor( public void Run([TimerTrigger("0 */60 0-12 * * *", RunOnStartup = true)] TimerInfo timer, ILogger log) { - string workItem = "{\"SubscriptionId\":\"\",\"Timestamp\":\"Sun, 01 Mar 2020 14:39:49 GMT\",\"JobId\":20200229,\"RetryCount\":0, \"IsRBACProcessed\": true}"; + string workItem = "{\"SubscriptionId\":\"\",\"Timestamp\":\"Sun, 01 Mar 2020 14:39:49 GMT\",\"JobId\":20200229,\"RetryCount\":0, \"IsRBACProcessed\": true}"; var workItemObject = JsonConvert.DeserializeObject(workItem); workItemObject.IsRBACProcessed = false; _subscriptionItemProcessor._log = log; - _subscriptionItemProcessor.ProcessSubscriptionItems(workItemObject); + var controlResults = _subscriptionItemProcessor.ProcessSubscriptionItems(workItemObject); + } } } \ No newline at end of file diff --git a/AzTS_Extended/Startup.cs b/AzTS_Extended/Startup.cs index afbe36d..9bd7e71 100644 --- a/AzTS_Extended/Startup.cs +++ b/AzTS_Extended/Startup.cs @@ -62,7 +62,6 @@ public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder bu var laQueryFilesPath = Path.Combine(configurationRootPath, "LAQueries"); _configuration = builder.ConfigurationBuilder .AddJsonFile(Path.Combine(configurationRootPath, "appsettings.json"), optional: false, reloadOnChange: true) - .AddJsonFile(Path.Combine(configurationRootPath, $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json"), optional: false, reloadOnChange: true) .AddKeyPerFile(laQueryFilesPath, true) .AddEnvironmentVariables() .Build(); diff --git a/AzTS_Extended/local.settings.json b/AzTS_Extended/local.settings.json index 326f1f1..0291c08 100644 --- a/AzTS_Extended/local.settings.json +++ b/AzTS_Extended/local.settings.json @@ -1,9 +1,12 @@ { "IsEncrypted": false, - "Values": { - "ASPNETCORE_ENVIRONMENT": "Local", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "FUNCTIONS_WORKER_RUNTIME": "dotnet", - "APPINSIGHTS_INSTRUMENTATIONKEY": "" - } + "Values": { + "ASPNETCORE_ENVIRONMENT": "Local", + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "FUNCTIONS_WORKER_RUNTIME": "dotnet", + "APPINSIGHTS_INSTRUMENTATIONKEY": "", + "AzureStorageSettings__ResourceId": "", + "LAConfigurations__WorkspaceId": "", + "LAConfigurations__ResourceId": "" + } } \ No newline at end of file From ccb6bb5d51eb55106141802bbb8f10b26883fdc4 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Mon, 1 Nov 2021 09:31:46 +0530 Subject: [PATCH 11/33] Update README.md --- README.md | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9abfae4..8d4f043 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,93 @@ -# AzTS-Samples -AzTS-Samples +# Org Policy Customization + +## Background + +The Azure Tenant Security Solution (AzTS) can be used to obtain visibility to cloud subscriptions and resource configuration across multiple subscriptions in an enterprise environment. +The AzTS is a logical progression of DevOps Kit which helps us move closer to an implementation of cloud security compliance solution using native security capabilities in Azure platform that are available today. Functionally, it is similar to running AzSK Continuous Assurance (CA) in central-scan mode. + +You can know more about AzTS [here](https://github.com/azsk/AzTS-docs). + +## Overview + +Org Policy Customization provides capabilities to modify existing controls and add new controls (for existing services supported by AzTS) to customize the AzTS for your organization as per your need. + +This feature enhances AzTS Solution by enabling tenant security compliance owners to: +1) Modify existing controls +2) Add new controls +3) Scan the controls locally [Stand-alone Solution] + +In this document, we will look at how to set up org policy, how to make modifications and additions to the controls, and how to accomplish various common org policy customization for the scanner. + +## Setting up org policy + +In this section, we will walk through the steps of setting up AzTS Scanner. + +> **Note**: You would require at least 'Reader' level access on Subscription and 'Contributor' level access to the LA Workspace, Storage, etc. + +Let's Start! + +1. Clone [this](https://github.com/azsk/AzTS-Samples) GitHub repository in a new Visual Studio. +2. Go to AzTS_Extended folder and load the AzTS_Extended.sln. +3. Files to update: + * In local.settings.json file: + 1. Application insights collect telemetry data from connected apps and provides Live Metrics, Log Analytics, etc. It has an instrumentation key which we need to configure into our function app i.e. APPINSIGHTS_INSTRUMENTATIONKEY and with this key app insights grab data from our app. Add instrumentation key for Application Insights by entering "APPINSIGHTS_INSTRUMENTATIONKEY" + 2. Storage Account and Log Analytic Workspace are used to store the scan events, inventory, subscription scan progress details and results. + 1. Add 'ResourceId' of the Storage Account (line 16), + 2. Add 'WorkspaceId' and 'ResourceId' of the LA Workspace (line 33-34) + * Mention the subscription to be scanned in Processor.cs, (line 33) +4. Build and Run + +This will install the required [NuGet packages](https://www.nuget.org/packages/Microsoft.AzTS.Azure.Scanner/). It will import the dependencies and dynamic linked libraries of the AzTS Scanner to the user's solution along with the following templates: + +| Template File | Description +| ---- | ---- | +| FeatureNameExt.json
[under the ControlConfigurationExt folder] | This file contains the setting of controls of a specific feature. A few meta-data are required for a control to be scanned which are mentioned in detail further ahead. +| FeatureNameControlEvaluatorExt.cs
[under the ControlEvaluator folder] | This file is used to override the base control evaluation method. + +Next, we will look into how to modify an existing control or add a new control through this setup. + +## Modifying and customizing org policy + +The typical workflow for all control changes will remain same and will involve the following basic steps: +1. Make modifications to the existing control metadata (Json files). +2. Add or Modify control methods in respective control evaluator files. +3. Build and Run + +Steps to modify/add a control: +1. **Control JSON:** + 1. Copy _FeatureNameExt.json_ file and rename it accordingly. For example: StorageExt.json + 2. Fill the parameters according to the feature. For example: + ``` JSON + { + "FeatureName": "Storage", + "Reference": "aka.ms/azsktcp/storage", + "IsMaintenanceMode": false, + } + ``` + 3. Add the control json with all parameters given in template. The following meta-data are required for a control to be scanned: + ``` JSON + "Controls": [ + { + "ControlID": "", + "Id": "", + "Automated": "Yes", + "MethodName": "", + "DisplayName": "", + "Enabled": false + } + ] + ``` + > *Note*: For **Id** above: If it is an existing control that you wish to modify, then use the same ID as used previously. If it is a new control, then follow a convention of a FeatureName followed by a *four* digit ID number. For example, "Storage1005" can be the ID for a new control implemented in Storage feature. + +2. **Control Evaluator:** + 1. Copy _FeatureNameControlEvaluatorExt.cs_ and rename it accordingly. For example: StorageControlEvaluatorExt.cs + 2. Change the FeatureNameEvaluatorExt and FeatureNameControlEvaluator according to the baseControlEvaluator name (line 13) as shown below. + ``` CS + // class FeatureNameEvaluatorExt : FeatureNameControlEvaluator + class StorageEvaluatorExt : StorageControlEvaluator + { + // Add control methods here + } + ``` + 3. Add the control method according to the feature documentation. From 9de91f88cc9f2a927cdaa3f11529e513faef1797 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Mon, 1 Nov 2021 10:46:40 +0530 Subject: [PATCH 12/33] Update README.md --- README.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8d4f043..4c3f092 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,18 @@ -# Org Policy Customization +# [Org Policy Customization](Readme.md#org-policy-customization) +- [Background](Readme.md#Background) +- [Overview](Readme.md#Overview) +- [Setting up org policy](Readme.md#setting-up-org-policy) +- [Modifying and customizing org policy](Readme.md#modifying-and-customizing-org-policy) +- [Common Application of Org Policy Customization](Readme.common-application-of-org-policy-customization) -## Background +## [Background](Readme.md#Background) The Azure Tenant Security Solution (AzTS) can be used to obtain visibility to cloud subscriptions and resource configuration across multiple subscriptions in an enterprise environment. The AzTS is a logical progression of DevOps Kit which helps us move closer to an implementation of cloud security compliance solution using native security capabilities in Azure platform that are available today. Functionally, it is similar to running AzSK Continuous Assurance (CA) in central-scan mode. You can know more about AzTS [here](https://github.com/azsk/AzTS-docs). -## Overview +## [Overview](Readme.md#Overview) Org Policy Customization provides capabilities to modify existing controls and add new controls (for existing services supported by AzTS) to customize the AzTS for your organization as per your need. @@ -18,7 +23,7 @@ This feature enhances AzTS Solution by enabling tenant security compliance owner In this document, we will look at how to set up org policy, how to make modifications and additions to the controls, and how to accomplish various common org policy customization for the scanner. -## Setting up org policy +## [Setting up org policy](Readme.md#setting-up-org-policy) In this section, we will walk through the steps of setting up AzTS Scanner. @@ -46,7 +51,7 @@ This will install the required [NuGet packages](https://www.nuget.org/packages/M Next, we will look into how to modify an existing control or add a new control through this setup. -## Modifying and customizing org policy +## [Modifying and customizing org policy](Readme.md#modifying-and-customizing-org-policy) The typical workflow for all control changes will remain same and will involve the following basic steps: 1. Make modifications to the existing control metadata (Json files). @@ -54,7 +59,7 @@ The typical workflow for all control changes will remain same and will involve t 3. Build and Run Steps to modify/add a control: -1. **Control JSON:** +1. [**Control JSON:**](Readme.md#control-json) 1. Copy _FeatureNameExt.json_ file and rename it accordingly. For example: StorageExt.json 2. Fill the parameters according to the feature. For example: ``` JSON @@ -79,7 +84,7 @@ Steps to modify/add a control: ``` > *Note*: For **Id** above: If it is an existing control that you wish to modify, then use the same ID as used previously. If it is a new control, then follow a convention of a FeatureName followed by a *four* digit ID number. For example, "Storage1005" can be the ID for a new control implemented in Storage feature. -2. **Control Evaluator:** +2. [**Control Evaluator:**](Readme.md#control-evaluator) 1. Copy _FeatureNameControlEvaluatorExt.cs_ and rename it accordingly. For example: StorageControlEvaluatorExt.cs 2. Change the FeatureNameEvaluatorExt and FeatureNameControlEvaluator according to the baseControlEvaluator name (line 13) as shown below. ``` CS From 9fb88b6a865e31ac87020798577a54cae5e49870 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Mon, 1 Nov 2021 10:48:24 +0530 Subject: [PATCH 13/33] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c3f092..e5573e4 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ - [Modifying and customizing org policy](Readme.md#modifying-and-customizing-org-policy) - [Common Application of Org Policy Customization](Readme.common-application-of-org-policy-customization) -## [Background](Readme.md#Background) +## [Background](README.md#Background) The Azure Tenant Security Solution (AzTS) can be used to obtain visibility to cloud subscriptions and resource configuration across multiple subscriptions in an enterprise environment. The AzTS is a logical progression of DevOps Kit which helps us move closer to an implementation of cloud security compliance solution using native security capabilities in Azure platform that are available today. Functionally, it is similar to running AzSK Continuous Assurance (CA) in central-scan mode. From 38958cef76b21bf95806869006f4ffa1c9a86425 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Mon, 1 Nov 2021 10:50:17 +0530 Subject: [PATCH 14/33] Update README.md --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e5573e4..5908d79 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# [Org Policy Customization](Readme.md#org-policy-customization) -- [Background](Readme.md#Background) -- [Overview](Readme.md#Overview) -- [Setting up org policy](Readme.md#setting-up-org-policy) -- [Modifying and customizing org policy](Readme.md#modifying-and-customizing-org-policy) -- [Common Application of Org Policy Customization](Readme.common-application-of-org-policy-customization) +# [Org Policy Customization](README.md#org-policy-customization) +- [Background](README.md#Background) +- [Overview](README.md#Overview) +- [Setting up org policy](README.md#setting-up-org-policy) +- [Modifying and customizing org policy](README.md#modifying-and-customizing-org-policy) +- [Common Application of Org Policy Customization](README.common-application-of-org-policy-customization) ## [Background](README.md#Background) @@ -12,7 +12,7 @@ The AzTS is a logical progression of DevOps Kit which helps us move closer to an You can know more about AzTS [here](https://github.com/azsk/AzTS-docs). -## [Overview](Readme.md#Overview) +## [Overview](README.md#Overview) Org Policy Customization provides capabilities to modify existing controls and add new controls (for existing services supported by AzTS) to customize the AzTS for your organization as per your need. @@ -23,7 +23,7 @@ This feature enhances AzTS Solution by enabling tenant security compliance owner In this document, we will look at how to set up org policy, how to make modifications and additions to the controls, and how to accomplish various common org policy customization for the scanner. -## [Setting up org policy](Readme.md#setting-up-org-policy) +## [Setting up org policy](README.md#setting-up-org-policy) In this section, we will walk through the steps of setting up AzTS Scanner. @@ -51,7 +51,7 @@ This will install the required [NuGet packages](https://www.nuget.org/packages/M Next, we will look into how to modify an existing control or add a new control through this setup. -## [Modifying and customizing org policy](Readme.md#modifying-and-customizing-org-policy) +## [Modifying and customizing org policy](README.md#modifying-and-customizing-org-policy) The typical workflow for all control changes will remain same and will involve the following basic steps: 1. Make modifications to the existing control metadata (Json files). @@ -59,7 +59,7 @@ The typical workflow for all control changes will remain same and will involve t 3. Build and Run Steps to modify/add a control: -1. [**Control JSON:**](Readme.md#control-json) +1. [**Control JSON:**](README.md#control-json) 1. Copy _FeatureNameExt.json_ file and rename it accordingly. For example: StorageExt.json 2. Fill the parameters according to the feature. For example: ``` JSON @@ -84,7 +84,7 @@ Steps to modify/add a control: ``` > *Note*: For **Id** above: If it is an existing control that you wish to modify, then use the same ID as used previously. If it is a new control, then follow a convention of a FeatureName followed by a *four* digit ID number. For example, "Storage1005" can be the ID for a new control implemented in Storage feature. -2. [**Control Evaluator:**](Readme.md#control-evaluator) +2. [**Control Evaluator:**](README.md#control-evaluator) 1. Copy _FeatureNameControlEvaluatorExt.cs_ and rename it accordingly. For example: StorageControlEvaluatorExt.cs 2. Change the FeatureNameEvaluatorExt and FeatureNameControlEvaluator according to the baseControlEvaluator name (line 13) as shown below. ``` CS From b7a3a1709469c83f1064dbdcac1e3fa604f047e1 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Mon, 1 Nov 2021 11:09:15 +0530 Subject: [PATCH 15/33] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5908d79..2b907c3 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,9 @@ Org Policy Customization provides capabilities to modify existing controls and a This feature enhances AzTS Solution by enabling tenant security compliance owners to: 1) Modify existing controls -2) Add new controls -3) Scan the controls locally [Stand-alone Solution] +2) Add new controls of existing features +3) Add new controls of new features (Coming soon) +4) Scan the controls locally [Stand-alone Solution] In this document, we will look at how to set up org policy, how to make modifications and additions to the controls, and how to accomplish various common org policy customization for the scanner. From 6dfd99221c50cce95fbf83e64ed915e1fa8a8201 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Mon, 1 Nov 2021 11:22:58 +0530 Subject: [PATCH 16/33] Update README.md --- README.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2b907c3..58cd2dc 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,29 @@ Steps to modify/add a control: } ] ``` - > *Note*: For **Id** above: If it is an existing control that you wish to modify, then use the same ID as used previously. If it is a new control, then follow a convention of a FeatureName followed by a *four* digit ID number. For example, "Storage1005" can be the ID for a new control implemented in Storage feature. + 1. For **Id** above: + * If it is an existing control that you wish to modify, then use the same ID as used previously. + * If it is a new control, then follow a convention of a FeatureName followed by a *four* digit ID number. For example, "Storage1005" can be the ID for a new control implemented in Storage feature. + 2. For **ControlID** above: Initial part of the control ID is pre-populated based on the service/feature and security domain you choose for the control (Azure_FeatureName_SecurityDomain_XXX). Please don't use spaces between words instead use underscore '_' to separate words in control ID. To see some of the examples of existing control IDs please check out this [list](https://github.com/azsk/AzTS-docs/tree/main/Control%20coverage#azure-services-supported-by-azts). + 3. Keep **Enabled** switch to 'Yes'. + 4. **DisplayName** is the user friendly name for the control. + + + > *Note*: You can provide additional details/optional settings for the control as listed below. + + |Settings| Description| Examples| + |-------------|------|---------| + |Automated| Whether the control is manual or automated| e.g. Yes/No (keep it Yes for policy based controls)| + |Description| A basic description on what the control is about| e.g. App Service must only be accessible over HTTPS. | + | Category| Generic security specification of the control.| e.g. Encrypt data in transit | + |Tags| Labels that denote the control being of a specific type or belonging to a specific domain | For e.g. Baseline, Automated etc.| + |Control Severity| The severity of the control| e.g. High: Should be remediated as soon as possible. Medium: Should be considered for remediation. Low: Remediation should be prioritized after high and medium.| + |Control Requirements| Prerequisites for the control.| e.g. Monitoring and auditing must be enabled and correctly configured according to prescribed organizational guidance| + |Rationale| Logical intention for the added control | e.g. Auditing enables log collection of important system events pertinent to security. Regular monitoring of audit logs can help to detect any suspicious and malicious activity early and respond in a timely manner.| + |Recommendations| Steps or guidance on how to remediate non-compliant resources | e.g. Refer https://azure.microsoft.com/en-in/documentation/articles/key-vault-get-started/ for configuring Key Vault and storing secrets | + |Custom Tags| Tags can be used for filtering and referring controls in the future while reporting| e.g. Production, Phase2 etc. | + |Control Settings| Settings specific to the control to be provided for the scan | e.g. Required TLS version for all App services in your tenant (Note: For policy based contols this should be empty) | + |Comments | These comments show up in the changelog for the feature. | e.g. Added new policy based control for App Service | 2. [**Control Evaluator:**](README.md#control-evaluator) 1. Copy _FeatureNameControlEvaluatorExt.cs_ and rename it accordingly. For example: StorageControlEvaluatorExt.cs @@ -96,4 +118,3 @@ Steps to modify/add a control: } ``` 3. Add the control method according to the feature documentation. - From 6c9a7146ab2c45e2e7065e7a3244ad8caedb1180 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Mon, 1 Nov 2021 11:41:21 +0530 Subject: [PATCH 17/33] Create README.md --- FeatureCoverage/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 FeatureCoverage/README.md diff --git a/FeatureCoverage/README.md b/FeatureCoverage/README.md new file mode 100644 index 0000000..907e5ac --- /dev/null +++ b/FeatureCoverage/README.md @@ -0,0 +1,13 @@ +## Security features covered by Azure Tenant Security (AzTS) + +This page displays security features that are implemented in AzTS. Features table listed under provide details about properties used within the existing control methods in form of CustomFields and how they can utilized in new custom methods. + +### Azure Services supported by AzTS + +|Feature Name|Resource Type| +|---|---| +|[AppService](Feature/AppService.md)|Microsoft.Web/sites| +|[Storage](Feature/Storage.md)|Microsoft.Storage/storageAccounts| +|[Subscription](Feature/SubscriptionCore.md)| + + From d2c4930ae3331d4b4d7cbb34ff3e50aa8e846eb0 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Mon, 1 Nov 2021 11:41:56 +0530 Subject: [PATCH 18/33] Create Storage.md --- FeatureCoverage/Feature/Storage.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 FeatureCoverage/Feature/Storage.md diff --git a/FeatureCoverage/Feature/Storage.md b/FeatureCoverage/Feature/Storage.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/FeatureCoverage/Feature/Storage.md @@ -0,0 +1 @@ + From 083d1936e4db3757d24a2e2d2145d1642a45f40d Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Mon, 1 Nov 2021 11:43:49 +0530 Subject: [PATCH 19/33] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58cd2dc..c66e25f 100644 --- a/README.md +++ b/README.md @@ -117,4 +117,4 @@ Steps to modify/add a control: // Add control methods here } ``` - 3. Add the control method according to the feature documentation. + 3. Add the control method according to the [feature documentation](FeatureCoverage/README.md). From f71fb457112cb6dabf2914e22eff0bf465709442 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Tue, 30 Nov 2021 09:20:41 +0530 Subject: [PATCH 20/33] Pushing all rework changes --- FeatureCoverage/Feature/AppService.md | 81 ++++++++ FeatureCoverage/Feature/Storage.md | 59 ++++++ FeatureCoverage/Feature/SubscriptionCore.md | 66 +++++++ FeatureCoverage/README.md | 3 +- README.md | 201 +++++++++++++++++--- 5 files changed, 385 insertions(+), 25 deletions(-) create mode 100644 FeatureCoverage/Feature/AppService.md create mode 100644 FeatureCoverage/Feature/SubscriptionCore.md diff --git a/FeatureCoverage/Feature/AppService.md b/FeatureCoverage/Feature/AppService.md new file mode 100644 index 0000000..be7e8fb --- /dev/null +++ b/FeatureCoverage/Feature/AppService.md @@ -0,0 +1,81 @@ +# AppService + +## Resource Type +Microsoft.Web/sites + +## Reference +Refer to [this document](https://github.com/azsk/AzTS-docs/blob/main/Control%20coverage/Feature/AppService.md) for meta-data and evaluation logic of the existing controls of AppService service. + +Certain Azure Policy or ARM APIs are used for evaluation. You can find below the mapping between the properties fetched from ARM APIs and the property name that can be used in the control evaluation while modifying/creating methods in FeatureNameEvaluatorExt class in the FeatureNameControlEvaluatorExt.cs. The properties fetched from ARM APIs are stored in JObject under the name CustomFields. There can be multiple CustomFields such as CustomFields1, CustomFields2, etc with different types of properties. The below mapping will guide you to write the control methods while extending the controls. + +## Properties + +**appService.CustomField1:** + +| Property Name | API Property | Type | +|---|---|---| +|HostNames|properties.hostNames|List| +|HostNameSslStates|properties.hostNameSslStates|string| +|AppServicePlan.SkuDescription.Capacity|properties.AppServicePlan.SkuDescription.Capacity|int| +|AppServicePlan.Name|properties.AppServicePlan.Name|string| +|HttpsEnabled|properties.httpsOnly|bool| +|ManagedServiceIdentityType|properties.identity.type|string| + +**appService.CustomField2:** + +| Property Name | API Property | Type | +|---|---|---| +| RemoteDebuggingEnabled | properties.RemoteDebuggingEnabled | bool | +|WebSocketEnabled |properties.webSocketsEnabled|bool| +|AlwaysOn|properties.alwaysOn|bool| +|HttpLoggingEnabled|properties.httpLoggingEnabled|bool| +|DetailedErrorLoggingEnabled|properties.detailedErrorLoggingEnabled|bool| +|RequestTracingEnabled|properties.requestTracingEnabled|bool| +|Cors|properties.cors|CorsSettings Model| +|MinTLSVersion|properties.minTlsVersion|string| +|IpSecurityRestrictions|properties.ipSecurityRestrictions|List(IpRule) where IpRule is defined model| +|ScmIpSecurityRestrictions|properties.scmIpSecurityRestrictions|List(IpRule) where IpRule is defined mode| +|ScmIpSecurityRestrictionsUseMain|properties.scmIpSecurityRestrictionsUseMain|bool| + +**appService.CustomField4:** +AppSvc.CF4 contains all the deployment slots +It can be accessed using the following: +``` CS +List deploymentSlots = JsonConvert.DeserializeObject>(appService.CustomField4); +``` + diff --git a/FeatureCoverage/Feature/Storage.md b/FeatureCoverage/Feature/Storage.md index 8b13789..233bb5d 100644 --- a/FeatureCoverage/Feature/Storage.md +++ b/FeatureCoverage/Feature/Storage.md @@ -1 +1,60 @@ +# Storage +## Resource Type +Microsoft.Storage/storageAccounts + +## Reference +Refer to [this document](https://github.com/azsk/AzTS-docs/blob/main/Control%20coverage/Feature/Storage.md) for meta-data and evaluation logic of the existing controls of Storage service. + +Certain Azure Policy or ARM APIs are used for evaluation. You can find below the mapping between the properties fetched from ARM APIs and the property name that can be used in the control evaluation while modifying/creating methods in FeatureNameEvaluatorExt class in the FeatureNameControlEvaluatorExt.cs. The properties fetched from ARM APIs are stored in JObject under the name CustomFields. There can be multiple CustomFields such as CustomFields1, CustomFields2, etc with different types of properties. The below mapping will guide you to write the control methods while extending the controls. + +## Properties + +**Storage.CustomField1:** + +| Property Name | API Property | Type | +|---|---|---| +| HttpsEnabled | properties.supportsHttpsTrafficOnly | bool | +| Kind |kind|string| +|ProvisioningState|properties.provisioningState|string| +|AllowBlobPublicAccess|properties.allowBlobPublicAccess|bool| +|NetworkRuleSet|properties.networkAcls.defaultAction|string| + +## Example + +``` CS +public class StorageControlEvaluator : BaseControlEvaluator +{ + public void CheckStorageNetworkAccess(Resource storage, ControlResult cr) + { + // We first check if CustomField1 is not NULL or empty + if (!string.IsNullOrEmpty(storage.CustomField1)) + { + + cr.VerificationResult = VerificationResultStatus.Failed; + + // CustomField1 has details about which protocol is supported by Storage for traffic + // Loading the JObject from a string that contains JSON. + var stgDetails = JObject.Parse(storage.CustomField1); + // Note how we use the property NetworkRuleSet here from the extracted JObject stgDetails. + string strNetworkRuleSet = stgDetails["NetworkRuleSet"].Value(); + + if (strNetworkRuleSet.Equals("Deny", StringComparison.OrdinalIgnoreCase)) + { + cr.StatusReason = $"Firewall and Virtual Network restrictions are defined for this storage"; + cr.VerificationResult = VerificationResultStatus.Passed; + } + else + { + cr.StatusReason = $"No Firewall and Virtual Network restrictions are defined for this storage"; + cr.VerificationResult = VerificationResultStatus.Failed; + } + } + + // 'Else' block not required since CustomField1 is never expected to be null + } + . + . + . +} +``` diff --git a/FeatureCoverage/Feature/SubscriptionCore.md b/FeatureCoverage/Feature/SubscriptionCore.md new file mode 100644 index 0000000..254cebe --- /dev/null +++ b/FeatureCoverage/Feature/SubscriptionCore.md @@ -0,0 +1,66 @@ +# Subscription + +## Resource Type +SubscriptionCore + +## Reference +Refer to [this document](https://github.com/azsk/AzTS-docs/blob/main/Control%20coverage/Feature/SubscriptionCore.md) for meta-data and evaluation logic of the existing controls of Subscription service. + +Certain Azure Policy or ARM APIs are used for evaluation. You can find below the mapping between the properties fetched from ARM APIs and the property name that can be used in the control evaluation while modifying/creating methods in FeatureNameEvaluatorExt class in the FeatureNameControlEvaluatorExt.cs. The properties fetched from ARM APIs are stored in JObject under the name CustomFields. There can be multiple CustomFields such as CustomFields1, CustomFields2, etc with different types of properties. The below mapping will guide you to write the control methods while extending the controls. + +## Properties + +**Subscription.CustomField2:** + +| Property Name | API Property | Type | +|---|---|---| +| autoProvision | properties.autoProvision | string | +|pricingTier|properties.pricingTier|string| + +**Subscription.CustomField3:** + +| Property Name | API Property | Type | +|---|---|---| + + +**Subscription.CustomField4:** + +| Property Name | API Property | Type | +|---|---|---| + + +## Example + +``` CS +public ControlResult CheckAutoProvisioningForSecurity(ControlResult cr) +{ + // We first check if CustomField1 is not NULL or empty + if (!string.IsNullOrWhiteSpace(this.Subscription.CustomField2)) //// CF2 contains security center details + { + // Notice how we deserializes the JSON to the specified model i.e. SecurityCenterModel + var securityCenterDetails = JsonConvert.DeserializeObject(this.Subscription.CustomField2); + + if (!securityCenterDetails.IsProviderRegistered) + { + cr.VerificationResult = VerificationResultStatus.Failed; + cr.StatusReason = "Security center provider not registered."; + return cr; + } + + cr.VerificationResult = VerificationResultStatus.Failed; + cr.StatusReason = $"Auto Provisioning setting is disabled for subscription. Provisioning Status:[{securityCenterDetails.AutoProvision}]"; + + if (securityCenterDetails.AutoProvision.Equals("on", StringComparison.OrdinalIgnoreCase)) + { + cr.VerificationResult = VerificationResultStatus.Passed; + cr.StatusReason = $"Auto Provisioning setting is enabled for subscription."; + } + } + + return cr; +} + . + . + . +} +``` diff --git a/FeatureCoverage/README.md b/FeatureCoverage/README.md index 907e5ac..3a32298 100644 --- a/FeatureCoverage/README.md +++ b/FeatureCoverage/README.md @@ -1,6 +1,6 @@ ## Security features covered by Azure Tenant Security (AzTS) -This page displays security features that are implemented in AzTS. Features table listed under provide details about properties used within the existing control methods in form of CustomFields and how they can utilized in new custom methods. +This page displays security features that are implemented in AzTS. Features table listed under provide details about properties used within the existing control methods in form of CustomFields and how they can utilized in new custom methods. This is for the purpose to guide users to implement new control for the respective features. ### Azure Services supported by AzTS @@ -10,4 +10,3 @@ This page displays security features that are implemented in AzTS. Features tabl |[Storage](Feature/Storage.md)|Microsoft.Storage/storageAccounts| |[Subscription](Feature/SubscriptionCore.md)| - diff --git a/README.md b/README.md index c66e25f..c9650ed 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,56 @@ +> The Azure Tenant Security Solution (AzTS) can be used to obtain visibility to cloud subscriptions and resource configuration across multiple subscriptions in an enterprise environment. +The AzTS is a logical progression of DevOps Kit which helps us move closer to an implementation of cloud security compliance solution using native security capabilities in Azure platform that are available today. Functionally, it is similar to running AzSK Continuous Assurance (CA) in central-scan mode. + +You can know more about AzTS [here](https://github.com/azsk/AzTS-docs). + # [Org Policy Customization](README.md#org-policy-customization) -- [Background](README.md#Background) -- [Overview](README.md#Overview) -- [Setting up org policy](README.md#setting-up-org-policy) -- [Modifying and customizing org policy](README.md#modifying-and-customizing-org-policy) -- [Common Application of Org Policy Customization](README.common-application-of-org-policy-customization) -## [Background](README.md#Background) +### [Overview](README.md#Overview) + - [When and why should I set up org policy?](Readme.md#when-and-why-should-i-setup-org-policy) -The Azure Tenant Security Solution (AzTS) can be used to obtain visibility to cloud subscriptions and resource configuration across multiple subscriptions in an enterprise environment. -The AzTS is a logical progression of DevOps Kit which helps us move closer to an implementation of cloud security compliance solution using native security capabilities in Azure platform that are available today. Functionally, it is similar to running AzSK Continuous Assurance (CA) in central-scan mode. +### [Setting up org policy](README.md#setting-up-org-policy) + -You can know more about AzTS [here](https://github.com/azsk/AzTS-docs). +### [Modifying and customizing org policy](README.md#modifying-and-customizing-org-policy) + - [Structure](Readme.md#structure) + - [Know more about controls](Readme.md#know-more-about-controls) + - [Steps to extend a control](Readme.md#steps-to-extend-a-control) +### [Common Application of Org Policy Customization](README.common-application-of-org-policy-customization) + +------------------------------------------------------ ## [Overview](README.md#Overview) -Org Policy Customization provides capabilities to modify existing controls and add new controls (for existing services supported by AzTS) to customize the AzTS for your organization as per your need. +#### When and why should I setup org policy + +When you run any scan from the AzTS, it relies on JSON-based policy files to determine various parameters that affect the behavior of the scan it is about to run. These policy files are downloaded 'on the fly' from a policy server. When you run the public version of the AzTS, the policy files are accessed from a CDN endpoint that is managed by the AzTS team. Thus, whenever you run a scan from a vanilla installation, AzTS accesses the CDN endpoint to get the latest policy configuration and runs the scan using it. + +The JSON inside the policy files dictate the behavior of the security scan. This includes things such as: + - Which set of controls to evaluate? + - What control set to use as a baseline? + - What settings/values to use for individual controls? + - What messages to display for recommendations? Etc. -This feature enhances AzTS Solution by enabling tenant security compliance owners to: -1) Modify existing controls -2) Add new controls of existing features -3) Add new controls of new features (Coming soon) -4) Scan the controls locally [Stand-alone Solution] +Note that the policy files needed for security scans are accessed from the last updated deployed AzTS package. -In this document, we will look at how to set up org policy, how to make modifications and additions to the controls, and how to accomplish various common org policy customization for the scanner. +While the out-of-box files in the package may be good for limited use, in many contexts you may want to "customize" the behavior of the security scans for your environment. You may want to do things such as: +(a) enable/disable some controls, +(b) change control settings to better match specific security policies within your org, +(c) change various messages, +(d) modify existing control logic +(e) add additional filter criteria for certain regulatory requirements that teams in your org can leverage, etc. +(f) add new controls to existing service + +When faced with such a need, you need a way to create and manage a dedicated policy endpoint customized to the needs of your environment. The organization policy customization setup feature helps you do that in an automated fashion. + +In this document, we will look at how to setup an organization-specific policy endpoint, how to make changes +to and manage the policy files and how to accomplish various common org-specific policy/behavior customizations +for the AzTS. ## [Setting up org policy](README.md#setting-up-org-policy) -In this section, we will walk through the steps of setting up AzTS Scanner. +In this section, we will walk through the steps of setting up organization-specific policy customizable AzTS Scanner locally. > **Note**: You would require at least 'Reader' level access on Subscription and 'Contributor' level access to the LA Workspace, Storage, etc. @@ -36,11 +60,25 @@ Let's Start! 2. Go to AzTS_Extended folder and load the AzTS_Extended.sln. 3. Files to update: * In local.settings.json file: + ```JSON + { + "IsEncrypted": false, + "Values": { + "ASPNETCORE_ENVIRONMENT": "Local", + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "FUNCTIONS_WORKER_RUNTIME": "dotnet", + "APPINSIGHTS_INSTRUMENTATIONKEY": "", + "AzureStorageSettings__ResourceId": "", + "LAConfigurations__WorkspaceId": "", + "LAConfigurations__ResourceId": "" + } + } + ``` 1. Application insights collect telemetry data from connected apps and provides Live Metrics, Log Analytics, etc. It has an instrumentation key which we need to configure into our function app i.e. APPINSIGHTS_INSTRUMENTATIONKEY and with this key app insights grab data from our app. Add instrumentation key for Application Insights by entering "APPINSIGHTS_INSTRUMENTATIONKEY" 2. Storage Account and Log Analytic Workspace are used to store the scan events, inventory, subscription scan progress details and results. - 1. Add 'ResourceId' of the Storage Account (line 16), - 2. Add 'WorkspaceId' and 'ResourceId' of the LA Workspace (line 33-34) - * Mention the subscription to be scanned in Processor.cs, (line 33) + 1. Add 'ResourceId' of the Storage Account, + 2. Add 'WorkspaceId' and 'ResourceId' of the LA Workspace + * Mention the ID of the subscription to be scanned in Processor.cs, (line 33) 4. Build and Run This will install the required [NuGet packages](https://www.nuget.org/packages/Microsoft.AzTS.Azure.Scanner/). It will import the dependencies and dynamic linked libraries of the AzTS Scanner to the user's solution along with the following templates: @@ -59,14 +97,102 @@ The typical workflow for all control changes will remain same and will involve t 2. Add or Modify control methods in respective control evaluator files. 3. Build and Run -Steps to modify/add a control: +### [Structure](README.md#structure) +Before we get started with extending the toolkit, let's understand the structure of the built solution repository. + + ├───AzTS_Extended + ├───Connected Services + ├───Dependencies + ├───Properties + ├───ConfigurationProvider + │ ├───ControlConfigurations + │ └───RoleDefinitionConfigurations + ├───Configurations + │ ├───LAQueries + ├───ControlConfigurationExt + ├───ControlEvaluator + + +### [Know more about controls](Readme.md#know-more-about-controls) + +All our controls inherit from a base class called BaseControlEvaluator which will take care of all the required plumbing from the control evaluation code. Every control will have a corresponding feature json file under the configurations folder. For example, Storage.cs (in the control evaluator folder) has a corresponding Storage.json file under configurations folder. These controls json have a bunch of configuration parameters, that can be controlled by a policy owner, for instance, you can change the recommendation, modify the description of the control suiting your org, change the severity, etc. + +Below is the typical schema for each control inside the feature json + +```JSON +{ + "ControlID": "Azure_Storage_NetSec_Restrict_Network_Access", //Human friendly control Id. The format used is Azure___ + "Description": "Ensure that Firewall and Virtual Network access is granted to a minimal set of trusted origins", //Description for the control, which is rendered in all the reports it generates (CSV, AI telemetry, emails etc.). + "Id": "AzureStorage260", //This is internal ID and should be unique. Since the ControlID can be modified, this internal ID ensures that we have a unique link to all the control results evaluation. + "ControlSeverity": "Medium", //Represents the severity of the Control. + "Automated": "Yes", //Indicates whether the given control is Manual/Automated. + "MethodName": "CheckStorageNetworkAccess", // Represents the Control method that is responsible to evaluate this control. It should be present inside the feature SVT associated with this control. + "DisplayName": "Ensure that Firewall and Virtual Network access is granted to a minimal set of trusted origins", // Represents human friendly name for the control. + "Recommendation": "Go to Azure Portal --> your Storage service --> Settings --> Firewalls and virtual networks --> Selected Network. Provide the specific IP address and Virtual Network details that should be allowed to access storage account.", //Recommendation typically provides the precise instructions on how to fix this control. + "Tags": [ + "SDL", + "TCP", + "Automated", + "NetSec", + "Baseline" + ], // You can decorate your control with different set of tags, that can be used as filters in scan commands. + "Enabled": true , //Defines whether the control is enabled or not. +    "Rationale": "Restricting access using firewall/virtual network config reduces network exposure of a storage account by limiting access only to expected range/set of clients. Note that this depends on the overall service architecture and may not be possible to implement in all scenarios." //Provides the intent of this control. +} +``` + +After Schema of the control json, let us look at the corresponding feature + +``` CS +public class StorageControlEvaluator : BaseControlEvaluator +{ + public void CheckStorageNetworkAccess(Resource storage, ControlResult cr) + { + // 1. This is where the code logic is placed + // 2. ControlResult input to this function, which needs to be updated with the verification Result (Passed/Failed/Verify/Manual/Error) based on the control logic + // 3. Messages that you add to ControlResult variable will be displayed in the detailed log automatically. + + if (!string.IsNullOrEmpty(storage.CustomField1)) + { + // Start with failed state, mark control as Passed if all required conditions are met + cr.VerificationResult = VerificationResultStatus.Failed; + cr.ScanSource = ScanResourceType.Reader.ToString(); + + // CustomField1 has details about which protocol is supported by Storage for traffic + var stgDetails = JObject.Parse(storage.CustomField1); + string strNetworkRuleSet = stgDetails["NetworkRuleSet"].Value(); + + if (strNetworkRuleSet.Equals("Deny", StringComparison.OrdinalIgnoreCase)) + { + // Firewall and Virtual Network restrictions are defined for this storage + cr.StatusReason = $"Firewall and Virtual Network restrictions are defined for this storage"; + cr.VerificationResult = VerificationResultStatus.Passed; + } + else + { + // No Firewall and Virtual Network restrictions are defined for this storage + cr.StatusReason = $"No Firewall and Virtual Network restrictions are defined for this storage"; + cr.VerificationResult = VerificationResultStatus.Failed; + } + } + + // 'Else' block not required since CustomField1 is never expected to be null + } + . + . + . +} +``` + + +### [Steps to extend a control](Readme.md#steps-to-extend-a-control) 1. [**Control JSON:**](README.md#control-json) 1. Copy _FeatureNameExt.json_ file and rename it accordingly. For example: StorageExt.json 2. Fill the parameters according to the feature. For example: ``` JSON { "FeatureName": "Storage", - "Reference": "aka.ms/azsktcp/storage", + "Reference": "aka.ms/azsktcp/storage", // you can find this from the FeatureName.json as well "IsMaintenanceMode": false, } ``` @@ -87,7 +213,7 @@ Steps to modify/add a control: * If it is an existing control that you wish to modify, then use the same ID as used previously. * If it is a new control, then follow a convention of a FeatureName followed by a *four* digit ID number. For example, "Storage1005" can be the ID for a new control implemented in Storage feature. 2. For **ControlID** above: Initial part of the control ID is pre-populated based on the service/feature and security domain you choose for the control (Azure_FeatureName_SecurityDomain_XXX). Please don't use spaces between words instead use underscore '_' to separate words in control ID. To see some of the examples of existing control IDs please check out this [list](https://github.com/azsk/AzTS-docs/tree/main/Control%20coverage#azure-services-supported-by-azts). - 3. Keep **Enabled** switch to 'Yes'. + 3. Keep **Enabled** switch to 'Yes' to scan a control. 4. **DisplayName** is the user friendly name for the control. @@ -118,3 +244,32 @@ Steps to modify/add a control: } ``` 3. Add the control method according to the [feature documentation](FeatureCoverage/README.md). + +## [Common Application of Org Policy Customization](README.common-application-of-org-policy-customization) + +1. Customizing/Changing the default Control Metadata + - You will be able to achieve the following scenarios using this feature: + 1. Update any of the properties of the control metadata according to your organization. The set of properties that you can modify ranges from ControlScanSource (i.e. change from ASCorReader to Reader) to Tags/CustomTags (i.e. add or remove a certain set of tags for a control). + 2. Update the baselines for your organization by modifying the tags/custom tags. + 3. Modify the ASC properties of a control. + "AssessmentProperties": { + "AssessmentNames": [ + "1c5de8e1-f68d-6a17-e0d2-ec259c42768c" + ], + } +2. Customizing the Control Method: + - You can update the control logic of any existing or new custom control. The user-defined method will get overlayed on the default control logic. +3. Adding a new Control for existing feature: + - Users can add a new custom control of existing features by custom Azure Policy or ASC Assessment. Both can be done leveraging this Org policy customization feature. + - On a high level, Users can do so by following the below mentioned steps: + 1. Add control metadata of the control in FeatureNameExt.json file. + 2. If the ControlScanSource is ASC based then add the AssessmentProperties as shown below: + "AssessmentProperties": { + "AssessmentNames": [ + "" + ], + } + 3. If the ControlScanSource is Reader based then implement the control logic in the corresponding Method in the FeatureNameControlEvaluatorExt.cs. + +4. Adding a new control of new feature (Coming Soon...) + From 5d0280903e9d4604f28d3ff6754f5a8a7c38483d Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Thu, 2 Dec 2021 23:26:07 +0530 Subject: [PATCH 21/33] Disabling Graph Configurations to remove errors --- AzTS_Extended/Configurations/appsettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AzTS_Extended/Configurations/appsettings.json b/AzTS_Extended/Configurations/appsettings.json index b0f6d34..8004d2d 100644 --- a/AzTS_Extended/Configurations/appsettings.json +++ b/AzTS_Extended/Configurations/appsettings.json @@ -136,7 +136,7 @@ }, "GraphConfigurations": { "BatchSize": 1000, - "IsFeatureEnabled": true + "IsFeatureEnabled": false }, "WorkItemProcessorSettings": { "BatchSize": 30000, From 73e540818e8d06d353ad14716028c1470811f111 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Fri, 3 Dec 2021 02:43:06 +0530 Subject: [PATCH 22/33] Removing LAQueries --- .../LAQueries/Inv_GetAllSubscriptionWorkItemsToProcess.kql | 7 ------- AzTS_Extended/Startup.cs | 2 -- 2 files changed, 9 deletions(-) delete mode 100644 AzTS_Extended/Configurations/LAQueries/Inv_GetAllSubscriptionWorkItemsToProcess.kql diff --git a/AzTS_Extended/Configurations/LAQueries/Inv_GetAllSubscriptionWorkItemsToProcess.kql b/AzTS_Extended/Configurations/LAQueries/Inv_GetAllSubscriptionWorkItemsToProcess.kql deleted file mode 100644 index 9529085..0000000 --- a/AzTS_Extended/Configurations/LAQueries/Inv_GetAllSubscriptionWorkItemsToProcess.kql +++ /dev/null @@ -1,7 +0,0 @@ -AzSK_SubInventory_CL -| where TimeGenerated > ago(2d) -| where JobId_d == toint(format_datetime(now(), 'yyyyMMdd')) -| where State_s != 'Disabled' -| summarize arg_max(TimeGenerated, *) by SubscriptionId -| project SubscriptionId -| distinct SubscriptionId \ No newline at end of file diff --git a/AzTS_Extended/Startup.cs b/AzTS_Extended/Startup.cs index 9bd7e71..d571a08 100644 --- a/AzTS_Extended/Startup.cs +++ b/AzTS_Extended/Startup.cs @@ -59,10 +59,8 @@ public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder bu throw new ArgumentException("App setting not found."); } - var laQueryFilesPath = Path.Combine(configurationRootPath, "LAQueries"); _configuration = builder.ConfigurationBuilder .AddJsonFile(Path.Combine(configurationRootPath, "appsettings.json"), optional: false, reloadOnChange: true) - .AddKeyPerFile(laQueryFilesPath, true) .AddEnvironmentVariables() .Build(); } From 52d83051a91498b8394fafca78689ac50e66b9a6 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Mon, 6 Dec 2021 17:39:35 +0530 Subject: [PATCH 23/33] Added new singletons and scopes --- AzTS_Extended/Startup.cs | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/AzTS_Extended/Startup.cs b/AzTS_Extended/Startup.cs index d571a08..dd88198 100644 --- a/AzTS_Extended/Startup.cs +++ b/AzTS_Extended/Startup.cs @@ -17,8 +17,11 @@ namespace AzTS_Extended using Microsoft.AzSK.ATS.Extensions.Graph; using Microsoft.AzSK.ATS.Extensions.HttpHelper; using Microsoft.AzSK.ATS.Extensions.Models; + using Microsoft.AzSK.ATS.Extensions.PolicyStateHelper; using Microsoft.AzSK.ATS.Extensions.PollyPolicyHelper; + using Microsoft.AzSK.ATS.Extensions.ResourceGraphHelper; using Microsoft.AzSK.ATS.Extensions.Storage; + using Microsoft.AzSK.ATS.Extensions.SubscriptionHelper; using Microsoft.AzSK.ATS.ProcessSubscriptions.Processors; using Microsoft.AzSK.ATS.ProcessSubscriptions.Repositories; using Microsoft.AzSK.ATS.ProcessSubscriptions.Repositories.ResourceRepositories; @@ -45,18 +48,12 @@ public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder bu FunctionsHostBuilderContext context = builder.GetContext(); // Get configurations paths - // var azure_root = $"{Environment.GetEnvironmentVariable("HOME")}/site/wwwroot"; string configurationRootPath = Path.Combine(context.ApplicationRootPath, "Configurations"); var temp = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); - /*if (!Directory.Exists(azure_root)) - { - azure_root = Directory.GetCurrentDirectory(); - configurationRootPath = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory() + @"\..\..\..\..\Configurations\Extended")); - }*/ if (string.IsNullOrWhiteSpace(configurationRootPath)) { - throw new ArgumentException("App setting not found."); + throw new ArgumentException("App setting not found"); } _configuration = builder.ConfigurationBuilder @@ -97,18 +94,14 @@ public override void Configure(IFunctionsHostBuilder builder) services.Configure(_configuration.GetSection(AzureControlScanExceptionSettings.ConfigName)); services.Configure(_configuration.GetSection(AADClientAppDetails.ConfigName)); services.Configure(_configuration.GetSection(AppMetadata.ConfigName)); - - // TODO: Check if this can be added + services.Configure(_configuration.GetSection(ARGConfigurations.ConfigName)); services.Configure(_configuration.GetSection(RepositorySettings.ConfigName)); - services.Configure(_configuration.GetSection(RuleEngineSettings.ConfigName)); // Notes: Named options pattern used for mapping configurations with strongly typed properties/classes services.Configure(_configuration.GetSection(WorkItemProcessorSettings.ConfigName)); // Helper classes registration - - // services.AddHttpClient().AddPolicyRegistry(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -125,19 +118,20 @@ public override void Configure(IFunctionsHostBuilder builder) services.AddScoped(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); // Repository classes registration services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -147,18 +141,8 @@ public override void Configure(IFunctionsHostBuilder builder) services.AddScoped(); services.AddSingleton(); services.AddScoped(); - // To handle "Scope disposed{no name, Parent=disposed{no name, Parent=disposed{no name}}} is disposed and scoped instances are disposed and no longer available" exception. - // TODO: Replace the timespan as need. eg(Timeout.InfiniteTimeSpan or TimeSpan.FromHours(2) for 2 hrs) - //_policyRegistry = services.AddPolicyRegistry(); - //PolicyHelper.CreateAndRegisterPolicies(_configuration, _policyRegistry); services.AddHttpClient(HttpClientConfig.HttpClientName).SetHandlerLifetime(TimeSpan.FromHours(2)); - // .AddPolicyHandler(httpRequestMessage => - //{ - // return _policyRegistry.Get>(PolicyHelper.PolicyName.WaitAndRetryPolicy); - //}); - - } } } \ No newline at end of file From 149fa8f54bfd85c9124c77a2ff6032022b889766 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Mon, 6 Dec 2021 18:03:17 +0530 Subject: [PATCH 24/33] Removing Resource graph error --- AzTS_Extended/Startup.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/AzTS_Extended/Startup.cs b/AzTS_Extended/Startup.cs index dd88198..56dc62a 100644 --- a/AzTS_Extended/Startup.cs +++ b/AzTS_Extended/Startup.cs @@ -18,8 +18,6 @@ namespace AzTS_Extended using Microsoft.AzSK.ATS.Extensions.HttpHelper; using Microsoft.AzSK.ATS.Extensions.Models; using Microsoft.AzSK.ATS.Extensions.PolicyStateHelper; - using Microsoft.AzSK.ATS.Extensions.PollyPolicyHelper; - using Microsoft.AzSK.ATS.Extensions.ResourceGraphHelper; using Microsoft.AzSK.ATS.Extensions.Storage; using Microsoft.AzSK.ATS.Extensions.SubscriptionHelper; using Microsoft.AzSK.ATS.ProcessSubscriptions.Processors; @@ -122,7 +120,6 @@ public override void Configure(IFunctionsHostBuilder builder) // Repository classes registration services.AddSingleton(); - services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); From 00f897d5f0e8c14c94b24f46fc679dec34d7ddaa Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Wed, 8 Dec 2021 12:44:28 +0530 Subject: [PATCH 25/33] Update Package Version --- AzTS_Extended/AzTS_Extended.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AzTS_Extended/AzTS_Extended.csproj b/AzTS_Extended/AzTS_Extended.csproj index 53a5541..1c92c87 100644 --- a/AzTS_Extended/AzTS_Extended.csproj +++ b/AzTS_Extended/AzTS_Extended.csproj @@ -18,7 +18,7 @@
- + @@ -51,4 +51,4 @@ Always - \ No newline at end of file + From d08dbd093f22707f20f46e2461a594351f2c6303 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Wed, 8 Dec 2021 13:21:54 +0530 Subject: [PATCH 26/33] Removing unneccesary LOC --- AzTS_Extended/AzTS_Extended.csproj | 6 ------ AzTS_Extended/Startup.cs | 1 - 2 files changed, 7 deletions(-) diff --git a/AzTS_Extended/AzTS_Extended.csproj b/AzTS_Extended/AzTS_Extended.csproj index 1c92c87..ea86e70 100644 --- a/AzTS_Extended/AzTS_Extended.csproj +++ b/AzTS_Extended/AzTS_Extended.csproj @@ -34,12 +34,6 @@ Always - - Always - - - Always - Always diff --git a/AzTS_Extended/Startup.cs b/AzTS_Extended/Startup.cs index 56dc62a..4d1ab93 100644 --- a/AzTS_Extended/Startup.cs +++ b/AzTS_Extended/Startup.cs @@ -71,7 +71,6 @@ public override void Configure(IFunctionsHostBuilder builder) // Add configurations from app settings // Enable inbuilt services - // services.AddHttpClient(); services.AddLogging(); services.AddApplicationInsightsTelemetry(); services.AddFeatureManagement(_configuration); From 1f92b65f82cbf0466200eb269fe1c6371cfcfd44 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Wed, 8 Dec 2021 16:43:01 +0530 Subject: [PATCH 27/33] Removed unnessasary LOC --- AzTS_Extended/AzTS_Extended.csproj | 9 -------- AzTS_Extended/Properties/launchSettings.json | 24 -------------------- 2 files changed, 33 deletions(-) delete mode 100644 AzTS_Extended/Properties/launchSettings.json diff --git a/AzTS_Extended/AzTS_Extended.csproj b/AzTS_Extended/AzTS_Extended.csproj index ea86e70..a197206 100644 --- a/AzTS_Extended/AzTS_Extended.csproj +++ b/AzTS_Extended/AzTS_Extended.csproj @@ -22,15 +22,6 @@ - - Always - - - Always - - - Always - Always diff --git a/AzTS_Extended/Properties/launchSettings.json b/AzTS_Extended/Properties/launchSettings.json deleted file mode 100644 index 9bcfd99..0000000 --- a/AzTS_Extended/Properties/launchSettings.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:50023", - "sslPort": 44375 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "AzTS_Extended": { - "commandName": "Project", - "launchBrowser": true, - "applicationUrl": "https://localhost:5001;http://localhost:5000" - } - } -} \ No newline at end of file From b97eeb75dfd371b254aee4a5bbe755ac6c55a998 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Thu, 9 Dec 2021 12:43:47 +0530 Subject: [PATCH 28/33] Enhacing Templates and Adding example files --- .../FeatureNameExt.json | 15 ----- .../FeatureNameExt_Template.json | 13 ++++ .../SubscriptionCoreExt.json | 16 +++++ ...eatureNameControlEvaluatorExt_Template.cs} | 0 .../SubscriptionCoreEvaluatorExt.cs | 63 +++++++++++++++++++ 5 files changed, 92 insertions(+), 15 deletions(-) delete mode 100644 AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json create mode 100644 AzTS_Extended/ControlConfigurationExt/FeatureNameExt_Template.json create mode 100644 AzTS_Extended/ControlConfigurationExt/SubscriptionCoreExt.json rename AzTS_Extended/ControlEvaluator/{FeatureNameControlEvaluatorExt.cs => FeatureNameControlEvaluatorExt_Template.cs} (100%) create mode 100644 AzTS_Extended/ControlEvaluator/SubscriptionCoreEvaluatorExt.cs diff --git a/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json b/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json deleted file mode 100644 index 5314cc6..0000000 --- a/AzTS_Extended/ControlConfigurationExt/FeatureNameExt.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "FeatureName": "", - "Reference": "", - "IsMaintenanceMode": false, - "Controls": [ - { - "ControlID": "", - "Id": "", - "Automated": "Yes", - "MethodName": "", - "DisplayName": "", - "Enabled": false - } - ] -} diff --git a/AzTS_Extended/ControlConfigurationExt/FeatureNameExt_Template.json b/AzTS_Extended/ControlConfigurationExt/FeatureNameExt_Template.json new file mode 100644 index 0000000..7ce9a79 --- /dev/null +++ b/AzTS_Extended/ControlConfigurationExt/FeatureNameExt_Template.json @@ -0,0 +1,13 @@ +{ + "FeatureName": "", // Represents Feature/Service name + "Controls": [ + { + "ControlID": "", // Represents human friendly control Id. The format used is Azure___ + "Id": "", // Represents internal ID and should be unique. Since the ControlID can be modified, this internal ID ensures that we have a unique link to all the control results evaluation. + "Automated": "Yes", // Indicates whether the given control is Manual/Automated. + "MethodName": "", // Represents the Control method that is responsible to evaluate this control. It should be present inside the feature SVT associated with this control. + "DisplayName": "", // Represents human friendly name for the control. + "Enabled": false // Defines whether the control is enabled or not. + } + ] +} diff --git a/AzTS_Extended/ControlConfigurationExt/SubscriptionCoreExt.json b/AzTS_Extended/ControlConfigurationExt/SubscriptionCoreExt.json new file mode 100644 index 0000000..5353794 --- /dev/null +++ b/AzTS_Extended/ControlConfigurationExt/SubscriptionCoreExt.json @@ -0,0 +1,16 @@ +{ + "FeatureName": "SubscriptionCore", + "Controls": [ + { + "ControlID": "Azure_Subscription_AuthZ_Limit_ClassicAdmin_Count", // Represents human friendly control Id. The format used is Azure___ + "Id": "SubscriptionCore160", // Represents internal ID and should be unique. Since the ControlID can be modified, this internal ID ensures that we have a unique link to all the control results evaluation. + "Automated": "Yes", // Indicates whether the given control is Manual/Automated. + "MethodName": "CheckCoAdminCount", // Represents the Control method that is responsible to evaluate this control. It should be present inside the feature SVT associated with this control. + "DisplayName": "Limit access per subscription to 2 or less classic administrators", // Represents human friendly name for the control. + "Enabled": true, // Defines whether the control is enabled or not. + "ControlSettings": { + "NoOfClassicAdminsLimit": 2 + } // Settings specific to the control to be provided for the scan + } + ] +} diff --git a/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs b/AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt_Template.cs similarity index 100% rename from AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt.cs rename to AzTS_Extended/ControlEvaluator/FeatureNameControlEvaluatorExt_Template.cs diff --git a/AzTS_Extended/ControlEvaluator/SubscriptionCoreEvaluatorExt.cs b/AzTS_Extended/ControlEvaluator/SubscriptionCoreEvaluatorExt.cs new file mode 100644 index 0000000..7a1bb91 --- /dev/null +++ b/AzTS_Extended/ControlEvaluator/SubscriptionCoreEvaluatorExt.cs @@ -0,0 +1,63 @@ +namespace AzTS_Extended.ControlEvaluator +{ + using Microsoft.AzSK.ATS.Extensions.Authorization; + using Microsoft.AzSK.ATS.Extensions.Models; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Models; + using Microsoft.AzSK.ATS.ProcessSubscriptions.Processors.ControlProcessors.ServiceControlEvaluators; + using Newtonsoft.Json.Linq; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + class SubscriptionCoreEvaluatorExt : SubscriptionCoreEvaluator + { + + public ControlResult CheckCoAdminCount(ControlResult cr) + { + + // 1. This is where the code logic is placed + // 2. ControlResult input to this function, which needs to be updated with the verification Result (Passed/Failed/Verify/Manual/Error) based on the control logic + // 3. Messages that you add to ControlResult variable will be displayed in the detailed log automatically. + + // Note the syntax of how to fetch value from Control Settings from the JSON. + int noOfClassicAdminsLimit = cr.ControlDetails.ControlSettings?["NoOfClassicAdminsLimit"]?.Value() ?? 2; + string classicAdminAccountsString = "No classic admin accounts found."; + int classicAdminAccountsCount = 0; + + // NOTE: While fetching RBAC result, we make three API calls - PIM, ARM, Classic. We are *not* handling partial result scenario if error occurred while fetching any of these RBAC result. + // If no RBAC is found, mark status as Verify because sufficient data is not available for evaluation. + if (this.RBACList?.Any() == false) + { + cr.VerificationResult = VerificationResultStatus.Verify; + cr.StatusReason = "No RBAC result found for this subscription."; + cr.ConsiderForCompliance = false; + return cr; + } + else + { + List classicAdminAccounts = new List(); + classicAdminAccounts = RBACList.AsParallel().Where(rbacItem => rbacItem.RoleName.ToLower().Contains("coadministrator") || rbacItem.RoleName.ToLower().Contains("serviceadministrator")).ToList(); + + // First start with default value, override this if classic admin account is found. + if (classicAdminAccounts != null && classicAdminAccounts.Any()) + { + classicAdminAccountsCount = classicAdminAccounts.Count; + classicAdminAccountsString = string.Join(",", classicAdminAccounts.Select(a => a.ToStringClassicAssignment()).ToList()); + } + + // Start with failed state, mark control as Passed if all required conditions are met + cr.StatusReason = $"No. of classic administrators found: [{classicAdminAccountsCount}]. Principal name results based on RBAC inv: [{String.Join(", ", classicAdminAccounts.Select(a => a.PrincipalName))}]"; + cr.VerificationResult = VerificationResultStatus.Failed; + + // Classic admin accounts count does not exceed the limit. + if (classicAdminAccountsCount <= noOfClassicAdminsLimit) + { + cr.VerificationResult = VerificationResultStatus.Passed; + } + } + + return cr; + } + } +} From d8ae391c24c9940975f78270f052772b20eed56f Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Sun, 12 Dec 2021 08:41:54 +0530 Subject: [PATCH 29/33] Adding gitignore file --- AzTS_Extended/.gitignore | 197 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 AzTS_Extended/.gitignore diff --git a/AzTS_Extended/.gitignore b/AzTS_Extended/.gitignore new file mode 100644 index 0000000..f5cacdf --- /dev/null +++ b/AzTS_Extended/.gitignore @@ -0,0 +1,197 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +*.pubxml +*profile.arm.json + +# NuGet Packages Directory +packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +!packages/build/ + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# Added by OneITVSO +*.dll +*.exe +/.vs/VSWorkspaceState.json +/.vs/slnx.sqlite + From 0c028eb75601ee3c8c0c0908f65020ec9cfafdb0 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Sun, 12 Dec 2021 08:49:35 +0530 Subject: [PATCH 30/33] Create .gitignore --- .gitignore | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..18735a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,200 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +*.pubxml +*profile.arm.json + +# NuGet Packages Directory +packages/* +## TODO: If the tool you use requires repositories.config +## uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since +# NuGet packages use it for MSBuild targets. +# This line needs to be after the ignore of the build folder +# (and the packages folder if the line above has been uncommented) +!packages/build/ + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# Added by OneITVSO +*.dll +*.exe +/.vs/VSWorkspaceState.json +/.vs/slnx.sqlite + + +.vs/ +**/packages/* From 52460de6fdc7f7b41026aa366dc6298dae3db743 Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Tue, 11 Jan 2022 06:18:25 +0530 Subject: [PATCH 31/33] Update Processor.cs --- AzTS_Extended/Processor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AzTS_Extended/Processor.cs b/AzTS_Extended/Processor.cs index c10af6b..16ae354 100644 --- a/AzTS_Extended/Processor.cs +++ b/AzTS_Extended/Processor.cs @@ -30,6 +30,7 @@ public Processor( public void Run([TimerTrigger("0 */60 0-12 * * *", RunOnStartup = true)] TimerInfo timer, ILogger log) { + // **Remember**: Before deploying, comment the `line 31` and `line 34` and comment out the `line 29` to make the *Run* function as queue-triggered instead of timer-triggered which is done for local testing purposes. string workItem = "{\"SubscriptionId\":\"\",\"Timestamp\":\"Sun, 01 Mar 2020 14:39:49 GMT\",\"JobId\":20200229,\"RetryCount\":0, \"IsRBACProcessed\": true}"; var workItemObject = JsonConvert.DeserializeObject(workItem); workItemObject.IsRBACProcessed = false; @@ -38,4 +39,4 @@ public void Run([TimerTrigger("0 */60 0-12 * * *", RunOnStartup = true)] TimerIn } } -} \ No newline at end of file +} From 893cf23b4a18474458964ad5ea2ad346f898d7a1 Mon Sep 17 00:00:00 2001 From: Freya Mehta Date: Tue, 11 Jan 2022 08:43:23 +0530 Subject: [PATCH 32/33] Removing the example file | Feedback changes --- .../SubscriptionCoreExt.json | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 AzTS_Extended/ControlConfigurationExt/SubscriptionCoreExt.json diff --git a/AzTS_Extended/ControlConfigurationExt/SubscriptionCoreExt.json b/AzTS_Extended/ControlConfigurationExt/SubscriptionCoreExt.json deleted file mode 100644 index 5353794..0000000 --- a/AzTS_Extended/ControlConfigurationExt/SubscriptionCoreExt.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "FeatureName": "SubscriptionCore", - "Controls": [ - { - "ControlID": "Azure_Subscription_AuthZ_Limit_ClassicAdmin_Count", // Represents human friendly control Id. The format used is Azure___ - "Id": "SubscriptionCore160", // Represents internal ID and should be unique. Since the ControlID can be modified, this internal ID ensures that we have a unique link to all the control results evaluation. - "Automated": "Yes", // Indicates whether the given control is Manual/Automated. - "MethodName": "CheckCoAdminCount", // Represents the Control method that is responsible to evaluate this control. It should be present inside the feature SVT associated with this control. - "DisplayName": "Limit access per subscription to 2 or less classic administrators", // Represents human friendly name for the control. - "Enabled": true, // Defines whether the control is enabled or not. - "ControlSettings": { - "NoOfClassicAdminsLimit": 2 - } // Settings specific to the control to be provided for the scan - } - ] -} From 1891648b8c45bbf2459a1c07518c8f00f449453b Mon Sep 17 00:00:00 2001 From: Freya Mehta <89447658+freyamehta-msft@users.noreply.github.com> Date: Tue, 11 Jan 2022 10:29:16 +0530 Subject: [PATCH 33/33] Update Processor.cs --- AzTS_Extended/Processor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AzTS_Extended/Processor.cs b/AzTS_Extended/Processor.cs index 16ae354..5a5e03c 100644 --- a/AzTS_Extended/Processor.cs +++ b/AzTS_Extended/Processor.cs @@ -31,7 +31,7 @@ public Processor( public void Run([TimerTrigger("0 */60 0-12 * * *", RunOnStartup = true)] TimerInfo timer, ILogger log) { // **Remember**: Before deploying, comment the `line 31` and `line 34` and comment out the `line 29` to make the *Run* function as queue-triggered instead of timer-triggered which is done for local testing purposes. - string workItem = "{\"SubscriptionId\":\"\",\"Timestamp\":\"Sun, 01 Mar 2020 14:39:49 GMT\",\"JobId\":20200229,\"RetryCount\":0, \"IsRBACProcessed\": true}"; + string workItem = "{\"SubscriptionId\":\"\"}"; var workItemObject = JsonConvert.DeserializeObject(workItem); workItemObject.IsRBACProcessed = false; _subscriptionItemProcessor._log = log;