@@ -903,6 +903,7 @@ def log_check(df):
903
903
df = df .rdd .map (lambda x : ( re .sub ('[\" \' \\ \\ ]' , '_' ,x [0 ]), x [1 ])).toDF (['config_name' , 'config_id' ])
904
904
logc = df .collect ()
905
905
logc_dict = {'audit_logs' : [[i .config_name , i .config_id ] for i in logc ]}
906
+
906
907
print (logc_dict )
907
908
return (check_id , 0 , logc_dict )
908
909
else :
@@ -995,6 +996,224 @@ def uc_check(df):
995
996
996
997
# COMMAND ----------
997
998
999
+ check_id = '53' # GOV-16 Workspace Unity Catalog metastore assignment
1000
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1001
+
1002
+ def uc_metasore_assignment (df ):
1003
+ if df is not None and not df .rdd .isEmpty ():
1004
+ uc_metasore = df .collect ()
1005
+ uc_metasore_dict = {i .metastore_id : [i .workspace_id ] for i in uc_metasore }
1006
+ return (check_id , 0 , uc_metasore_dict )
1007
+ else :
1008
+ return (check_id , 1 , {})
1009
+ if enabled :
1010
+ tbl_name = 'global_temp.unitycatalogmsv2' + '_' + workspace_id
1011
+ sql = f'''
1012
+ SELECT metastore_id,workspace_id
1013
+ FROM { tbl_name }
1014
+ WHERE workspace_id="{ workspaceId } "
1015
+
1016
+ '''
1017
+ sqlctrl (workspace_id , sql , uc_metasore_assignment )
1018
+
1019
+ # COMMAND ----------
1020
+
1021
+ check_id = '54' # GOV-17 Lifetime of metastore delta sharing recipient token set less than 90 days
1022
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1023
+
1024
+ def uc_metasore_token (df ):
1025
+ if df is not None and not df .rdd .isEmpty ():
1026
+ uc_metasore = df .collect ()
1027
+ uc_metasore_dict = {num : [row .name ,row .delta_sharing_recipient_token_lifetime_in_seconds ] for num ,row in enumerate (uc_metasore )}
1028
+ return (check_id , 1 , uc_metasore_dict )
1029
+ else :
1030
+ return (check_id , 0 , {})
1031
+ if enabled :
1032
+ tbl_name = 'global_temp.unitycatalogmsv1' + '_' + workspace_id
1033
+ sql = f'''
1034
+ SELECT name, delta_sharing_recipient_token_lifetime_in_seconds
1035
+ FROM { tbl_name }
1036
+ WHERE delta_sharing_scope ="INTERNAL_AND_EXTERNAL" AND delta_sharing_recipient_token_lifetime_in_seconds < 7776000
1037
+ '''
1038
+ sqlctrl (workspace_id , sql , uc_metasore_token )
1039
+
1040
+
1041
+ # COMMAND ----------
1042
+
1043
+ check_id = '55' # GOV-18 Check if there are any token based sharing without IP access lists ip_access_list
1044
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1045
+
1046
+ def uc_delta_share_ip_accesslist (df ):
1047
+ if df is not None and not df .rdd .isEmpty ():
1048
+ uc_metasore = df .collect ()
1049
+ uc_metasore_dict = {num : [row .name ,row .owner ] for num ,row in enumerate (uc_metasore )}
1050
+ return (check_id , 1 , uc_metasore_dict )
1051
+ else :
1052
+ return (check_id , 0 , {})
1053
+ if enabled :
1054
+ tbl_name = 'global_temp.unitycatalogsharerecipients' + '_' + workspace_id
1055
+ sql = f'''
1056
+ SELECT name, owner
1057
+ FROM { tbl_name }
1058
+ where authentication_type = 'TOKEN' and ip_access_list is NULL
1059
+ '''
1060
+ sqlctrl (workspace_id , sql , uc_delta_share_ip_accesslist )
1061
+
1062
+
1063
+ # COMMAND ----------
1064
+
1065
+ check_id = '56' # GOV-19 Check if Delta sharing Token Expiration
1066
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1067
+
1068
+ def uc_delta_share_expiration_time (df ):
1069
+ if df is not None and not df .rdd .isEmpty ():
1070
+ uc_metasore = df .collect ()
1071
+ uc_metasore_dict = {num : [row .name ,row .owner ] for num ,row in enumerate (uc_metasore )}
1072
+ return (check_id , 1 , uc_metasore_dict )
1073
+ else :
1074
+ return (check_id , 0 , {})
1075
+ if enabled :
1076
+ tbl_name = 'global_temp.unitycatalogsharerecipients' + '_' + workspace_id
1077
+ sql = f'''
1078
+ SELECT tokens.* FROM (select explode(tokens) as tokens, full_name, owner
1079
+ FROM { tbl_name }
1080
+ WHERE authentication_type = 'TOKEN') WHERE tokens.expiration_time is NULL
1081
+ '''
1082
+ sqlctrl (workspace_id , sql , uc_delta_share_expiration_time )
1083
+
1084
+
1085
+ # COMMAND ----------
1086
+
1087
+ check_id = '57' # GOV-20 Check Use of Metastore
1088
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1089
+
1090
+ def uc_metastore (df ):
1091
+ if df is not None and not df .rdd .isEmpty ():
1092
+ uc_metasore = df .collect ()
1093
+ uc_metasore_dict = {i .name : [i .owner ] for i in uc_metasore }
1094
+ return (check_id , 0 , uc_metasore_dict )
1095
+ else :
1096
+ return (check_id , 1 , {})
1097
+ if enabled :
1098
+ tbl_name = 'global_temp.unitycatalogmsv1' + '_' + workspace_id
1099
+ sql = f'''
1100
+ SELECT name,owner
1101
+ FROM { tbl_name }
1102
+ WHERE securable_type = 'METASTORE'
1103
+ '''
1104
+ sqlctrl (workspace_id , sql , uc_metastore )
1105
+
1106
+
1107
+ # COMMAND ----------
1108
+
1109
+ check_id = '58' # GOV-21 Check Metastore Admin is also the creator
1110
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1111
+
1112
+ def uc_metastore_owner (df ):
1113
+ if df is not None and not df .rdd .isEmpty ():
1114
+ uc_metasore = df .collect ()
1115
+ uc_metasore_dict = {i .name : [i .owner , i .created_by ] for i in uc_metasore }
1116
+ return (check_id , 1 , uc_metasore_dict )
1117
+ else :
1118
+ return (check_id , 0 , {})
1119
+ if enabled :
1120
+ tbl_name = 'global_temp.unitycatalogmsv1' + '_' + workspace_id
1121
+ sql = f'''
1122
+ SELECT name,owner,created_by
1123
+ FROM { tbl_name }
1124
+ WHERE securable_type = 'METASTORE' and owner == created_by
1125
+ '''
1126
+ sqlctrl (workspace_id , sql , uc_metastore_owner )
1127
+
1128
+
1129
+ # COMMAND ----------
1130
+
1131
+ check_id = '59' # GOV-22 Check Metastore Storage Credentials
1132
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1133
+
1134
+ def uc_metastore_storage_creds (df ):
1135
+ if df is not None and not df .rdd .isEmpty ():
1136
+ uc_metasore = df .collect ()
1137
+ uc_metasore_dict = {num : [row .name ,row .owner , row .created_by ] for num ,row in enumerate (uc_metasore )}
1138
+ return (check_id , 1 , uc_metasore_dict )
1139
+ else :
1140
+ return (check_id , 0 , {})
1141
+ if enabled :
1142
+ tbl_name = 'global_temp.unitycatalogcredentials' + '_' + workspace_id
1143
+ sql = f'''
1144
+ SELECT name,owner,created_by
1145
+ FROM { tbl_name }
1146
+ WHERE securable_type = "STORAGE_CREDENTIAL"
1147
+ '''
1148
+ sqlctrl (workspace_id , sql , uc_metastore_storage_creds )
1149
+
1150
+
1151
+ # COMMAND ----------
1152
+
1153
+ check_id = '60' # GOV-23 Check UC enabled Data warehouses
1154
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1155
+
1156
+ def uc_dws (df ):
1157
+ if df is not None and not df .rdd .isEmpty ():
1158
+ uc_metasore = df .collect ()
1159
+ uc_metasore_dict = {i .name : [i .creator_name ] for i in uc_metasore }
1160
+
1161
+ return (check_id , 1 , uc_metasore_dict )
1162
+ else :
1163
+ return (check_id , 0 , {})
1164
+ if enabled :
1165
+ tbl_name = 'global_temp.dbsql_warehouselistv2' + '_' + workspace_id
1166
+ sql = f'''
1167
+ SELECT warehouse.name as name , warehouse.creator_name as creator_name from (select explode(warehouses) as warehouse
1168
+ FROM { tbl_name } )
1169
+ where warehouse.disable_uc = true
1170
+ '''
1171
+ sqlctrl (workspace_id , sql , uc_dws )
1172
+
1173
+
1174
+ # COMMAND ----------
1175
+
1176
+ check_id = '61' # INFO-17 Check Serverless Compute enabled
1177
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1178
+
1179
+ def dbsql_enable_serverless_compute (df ):
1180
+ if df is not None and not df .rdd .isEmpty ():
1181
+ return (check_id , 0 , {'enable_serverless_compute' :'Serverless Compute enabled' } )
1182
+ else :
1183
+ return (check_id , 1 , {'enable_serverless_compute' :'Serverless Compute not enabled' })
1184
+ if enabled :
1185
+ tbl_name = 'global_temp.dbsql_workspaceconfig' + '_' + workspace_id
1186
+ sql = f'''
1187
+ SELECT enable_serverless_compute FROM
1188
+ FROM { tbl_name }
1189
+ WHERE enable_serverless_compute = true
1190
+ '''
1191
+ sqlctrl (workspace_id , sql , dbsql_enable_serverless_compute )
1192
+
1193
+
1194
+ # COMMAND ----------
1195
+
1196
+ check_id = '62' # INFO-18 Check Delta Sharing CREATE_RECIPIENT and CREATE_SHARE permissions
1197
+ enabled , sbp_rec = getSecurityBestPracticeRecord (check_id , cloud_type )
1198
+
1199
+ def metastore_delta_sharing_permissions (df ):
1200
+ if df is not None and not df .rdd .isEmpty ():
1201
+ uc_metasore = df .collect ()
1202
+ uc_metasore_dict = {num : [row .metastore_name ,row .principal , row .privilege ] for num ,row in enumerate (uc_metasore )}
1203
+ return (check_id , 0 , uc_metasore_dict ) # intentionally kept the score to 0 as its not a pass or fail. Its more of FYI
1204
+ else :
1205
+ return (check_id , 0 , {}) # intentionally kept the score to 0 as its not a pass or fail. Its more of FYI
1206
+ if enabled :
1207
+ tbl_name = 'global_temp.metastorepermissions' + '_' + workspace_id
1208
+ sql = f'''
1209
+ SELECT * FROM (SELECT metastore_name,principal,explode(privileges) as privilege
1210
+ FROM { tbl_name } )
1211
+ WHERE privilege= "CREATE_RECIPIENT" OR privilege="CREATE_SHARE"
1212
+ '''
1213
+ sqlctrl (workspace_id , sql , metastore_delta_sharing_permissions )
1214
+
1215
+ # COMMAND ----------
1216
+
998
1217
tcomp = time .time () - start_time
999
1218
print (f"Workspace Analysis - { tcomp } seconds to run" )
1000
1219
0 commit comments