|
| 1 | +/* create table if it doesn't exist |
| 2 | +create table dbo.memberships ( |
| 3 | + userObjectGUID varchar(255), |
| 4 | + groupObjectGUID varchar(255), |
| 5 | + hierarchy int, |
| 6 | + _inserted datetime2(0), |
| 7 | + _updated datetime2(0), |
| 8 | + _deleted datetime2(0) |
| 9 | +) |
| 10 | +*/ |
| 11 | + |
| 12 | + |
| 13 | +drop table if exists #userGroup; |
| 14 | +with cte as ( |
| 15 | + select |
| 16 | + objectGUID, |
| 17 | + memberOf = replace( |
| 18 | + replace( |
| 19 | + replace( |
| 20 | + replace( |
| 21 | + memberOf, |
| 22 | + '(', '['), |
| 23 | + ',)', ']'), |
| 24 | + ')', ']'), |
| 25 | + '''', '"') |
| 26 | + from dbo.users u |
| 27 | + where u.memberOf <> 'None' |
| 28 | +) |
| 29 | +select |
| 30 | + userObjectGUID = t.objectGUID |
| 31 | + ,groupObjectGUID = g.objectGUID |
| 32 | +into #userGroup |
| 33 | +from cte t |
| 34 | +cross apply OPENJSON(memberOf) as mo |
| 35 | +left join dbo.groups g |
| 36 | + on g.distinguishedName = mo.value |
| 37 | +; |
| 38 | + |
| 39 | +/* group that are members of groups */ |
| 40 | + |
| 41 | +drop table if exists #groupGroup; |
| 42 | +with cte as ( |
| 43 | + select |
| 44 | + g.objectGUID, |
| 45 | + memberOf = replace( |
| 46 | + replace( |
| 47 | + replace( |
| 48 | + replace( |
| 49 | + memberOf, |
| 50 | + '(', '['), |
| 51 | + ',)', ']'), |
| 52 | + ')', ']'), |
| 53 | + '''', '"') |
| 54 | + from dbo.groups g |
| 55 | + where memberOf <> 'None' |
| 56 | +) |
| 57 | +select |
| 58 | + groupObjectGUID = t.objectGUID |
| 59 | + ,memberOfObjectGUID = g.objectGUID |
| 60 | +into #groupGroup |
| 61 | +from cte t |
| 62 | +cross apply OPENJSON(memberOf) as mo |
| 63 | +left join dbo.groups g |
| 64 | + on g.distinguishedName = mo.value |
| 65 | +; |
| 66 | + |
| 67 | + |
| 68 | +/* join everything together where the next level is not already exists previously in the hierarchy, can probably be done with a loop.. but just doing 15 levels */ |
| 69 | +/* todo improve to be recrusive and dynamic, this was written in short time and I don't have access to this data anymore to improve it */ |
| 70 | +drop table if exists #grouphierarchy |
| 71 | +select |
| 72 | + userObjectGUID = u.userObjectGUID |
| 73 | + ,memberOfObjectGUID0 = u.groupObjectGUID |
| 74 | + ,memberOfObjectGUID1 = g1.memberOfObjectGUID |
| 75 | + ,memberOfObjectGUID2 = g2.memberOfObjectGUID |
| 76 | + ,memberOfObjectGUID3 = g3.memberOfObjectGUID |
| 77 | + ,memberOfObjectGUID4 = g4.memberOfObjectGUID |
| 78 | + ,memberOfObjectGUID5 = g5.memberOfObjectGUID |
| 79 | + ,memberOfObjectGUID6 = g6.memberOfObjectGUID |
| 80 | + ,memberOfObjectGUID7 = g7.memberOfObjectGUID |
| 81 | + ,memberOfObjectGUID8 = g8.memberOfObjectGUID |
| 82 | + ,memberOfObjectGUID9 = g9.memberOfObjectGUID |
| 83 | + ,memberOfObjectGUID10 = g10.memberOfObjectGUID |
| 84 | + ,memberOfObjectGUID11 = g11.memberOfObjectGUID |
| 85 | + ,memberOfObjectGUID12 = g12.memberOfObjectGUID |
| 86 | + ,memberOfObjectGUID13 = g13.memberOfObjectGUID |
| 87 | + ,memberOfObjectGUID14 = g14.memberOfObjectGUID |
| 88 | + ,memberOfObjectGUID15 = g15.memberOfObjectGUID |
| 89 | +into #grouphierarchy |
| 90 | +from #userGroup u |
| 91 | +left join #groupGroup g1 |
| 92 | + on g1.groupObjectGUID = u.groupObjectGUID |
| 93 | +left join #groupGroup g2 |
| 94 | + on g2.groupObjectGUID = g1.memberOfObjectGUID |
| 95 | + and g2.groupObjectGUID <> g1.groupObjectGUID |
| 96 | +left join #groupGroup g3 |
| 97 | + on g3.groupObjectGUID = g2.memberOfObjectGUID |
| 98 | + and g3.groupObjectGUID <> g1.groupObjectGUID |
| 99 | + and g3.groupObjectGUID <> g2.groupObjectGUID |
| 100 | +left join #groupGroup g4 |
| 101 | + on g4.groupObjectGUID = g3.memberOfObjectGUID |
| 102 | + and g4.groupObjectGUID <> g1.groupObjectGUID |
| 103 | + and g4.groupObjectGUID <> g2.groupObjectGUID |
| 104 | + and g4.groupObjectGUID <> g3.groupObjectGUID |
| 105 | +left join #groupGroup g5 |
| 106 | + on g5.groupObjectGUID = g4.memberOfObjectGUID |
| 107 | + and g5.groupObjectGUID <> g1.groupObjectGUID |
| 108 | + and g5.groupObjectGUID <> g2.groupObjectGUID |
| 109 | + and g5.groupObjectGUID <> g3.groupObjectGUID |
| 110 | + and g5.groupObjectGUID <> g4.groupObjectGUID |
| 111 | +left join #groupGroup g6 |
| 112 | + on g6.groupObjectGUID = g5.memberOfObjectGUID |
| 113 | + and g6.groupObjectGUID <> g1.groupObjectGUID |
| 114 | + and g6.groupObjectGUID <> g2.groupObjectGUID |
| 115 | + and g6.groupObjectGUID <> g3.groupObjectGUID |
| 116 | + and g6.groupObjectGUID <> g4.groupObjectGUID |
| 117 | + and g6.groupObjectGUID <> g5.groupObjectGUID |
| 118 | +left join #groupGroup g7 |
| 119 | + on g7.groupObjectGUID = g6.memberOfObjectGUID |
| 120 | + and g7.groupObjectGUID <> g1.groupObjectGUID |
| 121 | + and g7.groupObjectGUID <> g2.groupObjectGUID |
| 122 | + and g7.groupObjectGUID <> g3.groupObjectGUID |
| 123 | + and g7.groupObjectGUID <> g4.groupObjectGUID |
| 124 | + and g7.groupObjectGUID <> g5.groupObjectGUID |
| 125 | + and g7.groupObjectGUID <> g6.groupObjectGUID |
| 126 | +left join #groupGroup g8 |
| 127 | + on g8.groupObjectGUID = g7.memberOfObjectGUID |
| 128 | + and g8.groupObjectGUID <> g1.groupObjectGUID |
| 129 | + and g8.groupObjectGUID <> g2.groupObjectGUID |
| 130 | + and g8.groupObjectGUID <> g3.groupObjectGUID |
| 131 | + and g8.groupObjectGUID <> g4.groupObjectGUID |
| 132 | + and g8.groupObjectGUID <> g5.groupObjectGUID |
| 133 | + and g8.groupObjectGUID <> g6.groupObjectGUID |
| 134 | + and g8.groupObjectGUID <> g7.groupObjectGUID |
| 135 | +left join #groupGroup g9 |
| 136 | + on g9.groupObjectGUID = g8.memberOfObjectGUID |
| 137 | + and g9.groupObjectGUID <> g1.groupObjectGUID |
| 138 | + and g9.groupObjectGUID <> g2.groupObjectGUID |
| 139 | + and g9.groupObjectGUID <> g3.groupObjectGUID |
| 140 | + and g9.groupObjectGUID <> g4.groupObjectGUID |
| 141 | + and g9.groupObjectGUID <> g5.groupObjectGUID |
| 142 | + and g9.groupObjectGUID <> g6.groupObjectGUID |
| 143 | + and g9.groupObjectGUID <> g7.groupObjectGUID |
| 144 | + and g9.groupObjectGUID <> g8.groupObjectGUID |
| 145 | +left join #groupGroup g10 |
| 146 | + on g10.groupObjectGUID = g9.memberOfObjectGUID |
| 147 | + and g10.groupObjectGUID <> g1.groupObjectGUID |
| 148 | + and g10.groupObjectGUID <> g2.groupObjectGUID |
| 149 | + and g10.groupObjectGUID <> g3.groupObjectGUID |
| 150 | + and g10.groupObjectGUID <> g4.groupObjectGUID |
| 151 | + and g10.groupObjectGUID <> g5.groupObjectGUID |
| 152 | + and g10.groupObjectGUID <> g6.groupObjectGUID |
| 153 | + and g10.groupObjectGUID <> g7.groupObjectGUID |
| 154 | + and g10.groupObjectGUID <> g8.groupObjectGUID |
| 155 | + and g10.groupObjectGUID <> g9.groupObjectGUID |
| 156 | +left join #groupGroup g11 |
| 157 | + on g11.groupObjectGUID = g10.memberOfObjectGUID |
| 158 | + and g11.groupObjectGUID <> g1.groupObjectGUID |
| 159 | + and g11.groupObjectGUID <> g2.groupObjectGUID |
| 160 | + and g11.groupObjectGUID <> g3.groupObjectGUID |
| 161 | + and g11.groupObjectGUID <> g4.groupObjectGUID |
| 162 | + and g11.groupObjectGUID <> g5.groupObjectGUID |
| 163 | + and g11.groupObjectGUID <> g6.groupObjectGUID |
| 164 | + and g11.groupObjectGUID <> g7.groupObjectGUID |
| 165 | + and g11.groupObjectGUID <> g8.groupObjectGUID |
| 166 | + and g11.groupObjectGUID <> g9.groupObjectGUID |
| 167 | + and g11.groupObjectGUID <> g10.groupObjectGUID |
| 168 | +left join #groupGroup g12 |
| 169 | + on g12.groupObjectGUID = g11.memberOfObjectGUID |
| 170 | + and g12.groupObjectGUID <> g1.groupObjectGUID |
| 171 | + and g12.groupObjectGUID <> g2.groupObjectGUID |
| 172 | + and g12.groupObjectGUID <> g3.groupObjectGUID |
| 173 | + and g12.groupObjectGUID <> g4.groupObjectGUID |
| 174 | + and g12.groupObjectGUID <> g5.groupObjectGUID |
| 175 | + and g12.groupObjectGUID <> g6.groupObjectGUID |
| 176 | + and g12.groupObjectGUID <> g7.groupObjectGUID |
| 177 | + and g12.groupObjectGUID <> g8.groupObjectGUID |
| 178 | + and g12.groupObjectGUID <> g9.groupObjectGUID |
| 179 | + and g12.groupObjectGUID <> g10.groupObjectGUID |
| 180 | + and g12.groupObjectGUID <> g11.groupObjectGUID |
| 181 | +left join #groupGroup g13 |
| 182 | + on g13.groupObjectGUID = g12.memberOfObjectGUID |
| 183 | + and g13.groupObjectGUID <> g1.groupObjectGUID |
| 184 | + and g13.groupObjectGUID <> g2.groupObjectGUID |
| 185 | + and g13.groupObjectGUID <> g3.groupObjectGUID |
| 186 | + and g13.groupObjectGUID <> g4.groupObjectGUID |
| 187 | + and g13.groupObjectGUID <> g5.groupObjectGUID |
| 188 | + and g13.groupObjectGUID <> g6.groupObjectGUID |
| 189 | + and g13.groupObjectGUID <> g7.groupObjectGUID |
| 190 | + and g13.groupObjectGUID <> g8.groupObjectGUID |
| 191 | + and g13.groupObjectGUID <> g9.groupObjectGUID |
| 192 | + and g13.groupObjectGUID <> g10.groupObjectGUID |
| 193 | + and g13.groupObjectGUID <> g11.groupObjectGUID |
| 194 | + and g13.groupObjectGUID <> g12.groupObjectGUID |
| 195 | +left join #groupGroup g14 |
| 196 | + on g14.groupObjectGUID = g12.memberOfObjectGUID |
| 197 | + and g14.groupObjectGUID <> g1.groupObjectGUID |
| 198 | + and g14.groupObjectGUID <> g2.groupObjectGUID |
| 199 | + and g14.groupObjectGUID <> g3.groupObjectGUID |
| 200 | + and g14.groupObjectGUID <> g4.groupObjectGUID |
| 201 | + and g14.groupObjectGUID <> g5.groupObjectGUID |
| 202 | + and g14.groupObjectGUID <> g6.groupObjectGUID |
| 203 | + and g14.groupObjectGUID <> g7.groupObjectGUID |
| 204 | + and g14.groupObjectGUID <> g8.groupObjectGUID |
| 205 | + and g14.groupObjectGUID <> g9.groupObjectGUID |
| 206 | + and g14.groupObjectGUID <> g10.groupObjectGUID |
| 207 | + and g14.groupObjectGUID <> g11.groupObjectGUID |
| 208 | + and g14.groupObjectGUID <> g12.groupObjectGUID |
| 209 | + and g14.groupObjectGUID <> g13.groupObjectGUID |
| 210 | +left join #groupGroup g15 |
| 211 | + on g15.groupObjectGUID = g12.memberOfObjectGUID |
| 212 | + and g15.groupObjectGUID <> g1.groupObjectGUID |
| 213 | + and g15.groupObjectGUID <> g2.groupObjectGUID |
| 214 | + and g15.groupObjectGUID <> g3.groupObjectGUID |
| 215 | + and g15.groupObjectGUID <> g4.groupObjectGUID |
| 216 | + and g15.groupObjectGUID <> g5.groupObjectGUID |
| 217 | + and g15.groupObjectGUID <> g6.groupObjectGUID |
| 218 | + and g15.groupObjectGUID <> g7.groupObjectGUID |
| 219 | + and g15.groupObjectGUID <> g8.groupObjectGUID |
| 220 | + and g15.groupObjectGUID <> g9.groupObjectGUID |
| 221 | + and g15.groupObjectGUID <> g10.groupObjectGUID |
| 222 | + and g15.groupObjectGUID <> g11.groupObjectGUID |
| 223 | + and g15.groupObjectGUID <> g12.groupObjectGUID |
| 224 | + and g15.groupObjectGUID <> g13.groupObjectGUID |
| 225 | + and g15.groupObjectGUID <> g14.groupObjectGUID |
| 226 | +; |
| 227 | + |
| 228 | +/* add it together to a single table with level */ |
| 229 | +drop table if exists #temp |
| 230 | +create table #temp ( |
| 231 | + userObjectGUID varchar(255), |
| 232 | + groupObjectGUID varchar(255), |
| 233 | + hierarchy int |
| 234 | +) |
| 235 | + |
| 236 | + |
| 237 | +declare @i int = 0; /* starting at 0 as the group that a user is direct member of */ |
| 238 | +declare @nr varchar(10); |
| 239 | +declare @sql nvarchar(max); |
| 240 | + |
| 241 | +while @i <= 15 |
| 242 | +begin |
| 243 | + |
| 244 | + set @nr = cast(@i as varchar(10)); |
| 245 | + set @sql = 'insert into #temp |
| 246 | + select |
| 247 | + userObjectGUID |
| 248 | + ,memberOfObjectGUID' + @nr + ' |
| 249 | + ,hierarchy = ' + @nr + ' |
| 250 | + from #grouphierarchy t |
| 251 | + where t.memberOfObjectGUID' + @nr + ' is not null'; |
| 252 | + exec(@sql); |
| 253 | + |
| 254 | + set @i += 1; |
| 255 | +end |
| 256 | +; |
| 257 | + |
| 258 | + |
| 259 | + |
| 260 | +/******************************************************************************** |
| 261 | +
|
| 262 | + merge with memberships table |
| 263 | +
|
| 264 | +*********************************************************************************/ |
| 265 | + |
| 266 | +with cte as ( |
| 267 | + select |
| 268 | + userObjectGUID |
| 269 | + ,groupObjectGUID |
| 270 | + ,hierarchy = min(t.hierarchy) |
| 271 | + from #temp t |
| 272 | + group by |
| 273 | + userObjectGUID |
| 274 | + ,groupObjectGUID |
| 275 | +) |
| 276 | +merge dbo.memberships t |
| 277 | +using cte s |
| 278 | + on s.userObjectGUID = t.userObjectGUID |
| 279 | + and s.groupObjectGUID = t.groupObjectGUID |
| 280 | +when matched and ( |
| 281 | + s.hierarchy <> t.hierarchy |
| 282 | + or t._deleted is not null |
| 283 | +) then update |
| 284 | +set |
| 285 | + t.hierarchy = s.hierarchy |
| 286 | + ,t._updated = getdate() |
| 287 | + ,t._deleted = null |
| 288 | +when not matched by target then |
| 289 | +insert ( |
| 290 | + userobjectGUID |
| 291 | + ,groupObjectGUID |
| 292 | + ,hierarchy |
| 293 | + ,_inserted |
| 294 | + ,_updated |
| 295 | +) |
| 296 | +values ( |
| 297 | + s.userobjectGUID |
| 298 | + ,s.groupObjectGUID |
| 299 | + ,s.hierarchy |
| 300 | + ,getdate() |
| 301 | + ,getdate() |
| 302 | +) |
| 303 | +when not matched by source and t._deleted is null then update |
| 304 | +set |
| 305 | + t._deleted = getdate() |
0 commit comments