@@ -24,80 +24,6 @@ type databaseSyncer struct {
2424 client * mssqldb.Client
2525}
2626
27- var databasePermissions = map [string ]string {
28- "AADS" : "Alter Any Database Event Session" ,
29- "AAMK" : "Alter Any Mask" ,
30- "AEDS" : "Alter Any External Data Source" ,
31- "AEFF" : "Alter Any External File Format" ,
32- "AL" : "Alter" ,
33- "ALAK" : "Alter Any Asymmetric Key" ,
34- "ALAR" : "Alter Any Application Role" ,
35- "ALAS" : "Alter Any Assembly" ,
36- "ALCF" : "Alter Any Certificate" ,
37- "ALDS" : "Alter Any Dataspace" ,
38- "ALED" : "Alter Any Database Event Notification" ,
39- "ALFT" : "Alter Any Fulltext Catalog" ,
40- "ALMT" : "Alter Any Message Type" ,
41- "ALRL" : "Alter Any Role" ,
42- "ALRT" : "Alter Any Route" ,
43- "ALSB" : "Alter Any Remote Service Binding" ,
44- "ALSC" : "Alter Any Contract" ,
45- "ALSK" : "Alter Any Symmetric Key" ,
46- "ALSM" : "Alter Any Schema" ,
47- "ALSV" : "Alter Any Service" ,
48- "ALTG" : "Alter Any Database DDL Trigger" ,
49- "ALUS" : "Alter Any User" ,
50- "AUTH" : "Authenticate" ,
51- "BADB" : "Backup Database" ,
52- "BALO" : "Backup Log" ,
53- "CL" : "Control" ,
54- "CO" : "Connect" ,
55- "CORP" : "Connect Replication" ,
56- "CP" : "Checkpoint" ,
57- "CRAG" : "Create Aggregate" ,
58- "CRAK" : "Create Asymmetric Key" ,
59- "CRAS" : "Create Certificate" ,
60- "CRDB" : "Create Fatabase" ,
61- "CRDF" : "Create Default" ,
62- "CRED" : "Create Database DDL Event Notification" ,
63- "CRFN" : "Create Function" ,
64- "CRFT" : "Create Fulltext Catalog" ,
65- "CRMT" : "Create Message Type" ,
66- "CRPR" : "Create Procedure" ,
67- "CRQU" : "Create Queue" ,
68- "CRRL" : "Create Role" ,
69- "CRRT" : "Create Route" ,
70- "CRRU" : "Create Rule" ,
71- "CRSB" : "Create Remote Service Binding" ,
72- "CRSC" : "Create contract" ,
73- "CRSK" : "Create symmetric key" ,
74- "CRSM" : "Create Schema" ,
75- "CRSN" : "Create Synonym" ,
76- "CRSO" : "Create Sequence" ,
77- "CRSV" : "Create Service" ,
78- "CRTB" : "Create Table" ,
79- "CRTY" : "Create Type" ,
80- "CRVW" : "Create View" ,
81- "CRXS" : "Create XML Schema Collection" ,
82- "DL" : "Delete" ,
83- "DABO" : "Administer Database Bulk Operations" ,
84- "EAES" : "Execute Any External Script" ,
85- "EX" : "Execute" ,
86- "IN" : "Insert" ,
87- "RC" : "Receive Object" ,
88- "RF" : "References" ,
89- "SL" : "Select" ,
90- "SPLN" : "Showplan" ,
91- "SUQN" : "Subscribe Query Notifications" ,
92- "TO" : "Take Ownership" ,
93- "UP" : "Update" ,
94- "VW" : "View Definition" ,
95- "VWCK" : "View Any Column Encryption Key Definition" ,
96- "VWCM" : "View Any Column Master Key Definition" ,
97- "VWCT" : "View Change Tracking" ,
98- "VWDS" : "View Database State Database" ,
99- }
100-
10127func (d * databaseSyncer ) ResourceType (ctx context.Context ) * v2.ResourceType {
10228 return d .resourceType
10329}
@@ -137,7 +63,7 @@ func (d *databaseSyncer) List(ctx context.Context, parentResourceID *v2.Resource
13763func (d * databaseSyncer ) Entitlements (ctx context.Context , resource * v2.Resource , pToken * pagination.Token ) ([]* v2.Entitlement , string , annotations.Annotations , error ) {
13864 var ret []* v2.Entitlement
13965
140- for key , name := range databasePermissions {
66+ for key , name := range mssqldb . DatabasePermissions {
14167 grantSlug := fmt .Sprintf ("%s (With Grant)" , name )
14268 ret = append (ret ,
14369 & v2.Entitlement {
@@ -146,13 +72,15 @@ func (d *databaseSyncer) Entitlements(ctx context.Context, resource *v2.Resource
14672 Slug : name ,
14773 Purpose : v2 .Entitlement_PURPOSE_VALUE_PERMISSION ,
14874 Resource : resource ,
75+ GrantableTo : []* v2.ResourceType {resourceTypeUser },
14976 },
15077 & v2.Entitlement {
15178 Id : enTypes .NewEntitlementID (resource , key + "-grant" ),
15279 DisplayName : grantSlug ,
15380 Slug : grantSlug ,
15481 Purpose : v2 .Entitlement_PURPOSE_VALUE_PERMISSION ,
15582 Resource : resource ,
83+ GrantableTo : []* v2.ResourceType {resourceTypeUser },
15684 })
15785 }
15886
@@ -182,7 +110,7 @@ func (d *databaseSyncer) Grants(ctx context.Context, resource *v2.Resource, pTok
182110 perms := strings .Split (p .Permissions , "," )
183111 for _ , perm := range perms {
184112 perm = strings .TrimSpace (perm )
185- if _ , ok := databasePermissions [perm ]; ok {
113+ if _ , ok := mssqldb . DatabasePermissions [perm ]; ok {
186114 rt , err := resourceTypeFromDatabasePrincipal (p .PrincipalType )
187115 if err != nil {
188116 l .Error ("unexpected principal type" , zap .String ("principal_type" , p .PrincipalType ))
@@ -232,6 +160,106 @@ func (d *databaseSyncer) Grants(ctx context.Context, resource *v2.Resource, pTok
232160 return ret , nextPageToken , nil , nil
233161}
234162
163+ func (d * databaseSyncer ) Grant (ctx context.Context , resource * v2.Resource , entitlement * v2.Entitlement ) ([]* v2.Grant , annotations.Annotations , error ) {
164+ l := ctxzap .Extract (ctx )
165+
166+ if resource .Id .ResourceType != resourceTypeUser .Id {
167+ return nil , nil , fmt .Errorf ("resource type %s is not supported for granting" , resource .Id .ResourceType )
168+ }
169+
170+ splitId := strings .Split (entitlement .Id , ":" )
171+ if len (splitId ) != 3 {
172+ return nil , nil , fmt .Errorf ("unexpected entitlement id: %s" , entitlement .Id )
173+ }
174+
175+ dbId , err := strconv .ParseInt (splitId [1 ], 10 , 64 )
176+ if err != nil {
177+ return nil , nil , fmt .Errorf ("unexpected database id: %s" , splitId [1 ])
178+ }
179+
180+ permission := splitId [2 ]
181+ isGrant := strings .Contains (permission , "-grant" )
182+ if isGrant {
183+ permission = strings .Replace (permission , "-grant" , "" , 1 )
184+ }
185+
186+ database , err := d .client .GetDatabase (ctx , dbId )
187+ if err != nil {
188+ return nil , nil , err
189+ }
190+
191+ user , err := d .client .GetUserPrincipal (ctx , resource .Id .Resource )
192+ if err != nil {
193+ return nil , nil , err
194+ }
195+
196+ dbUser , err := d .client .GetUserFromDb (ctx , database .Name , resource .Id .Resource )
197+ if err != nil {
198+ return nil , nil , err
199+ }
200+
201+ if dbUser == nil {
202+ l .Info ("user not found in database, creating user for principal" , zap .String ("user" , resource .Id .Resource ))
203+
204+ err = d .client .CreateDatabaseUserForPrincipal (ctx , database .Name , user .Name )
205+ if err != nil {
206+ return nil , nil , err
207+ }
208+ }
209+
210+ err = d .client .GrantPermissionOnDatabase (ctx , permission , database .Name , user .Name )
211+ if err != nil {
212+ return nil , nil , err
213+ }
214+
215+ entitlementName := permission
216+ if isGrant {
217+ entitlementName = permission + "-grant"
218+ }
219+
220+ newGrant := grTypes .NewGrant (resource , entitlementName , & v2.ResourceId {
221+ Resource : user .ID ,
222+ ResourceType : resourceTypeUser .Id ,
223+ })
224+
225+ return []* v2.Grant {newGrant }, nil , nil
226+ }
227+
228+ func (d * databaseSyncer ) Revoke (ctx context.Context , grant * v2.Grant ) (annotations.Annotations , error ) {
229+ l := ctxzap .Extract (ctx )
230+
231+ if grant .Principal .Id .ResourceType != resourceTypeUser .Id {
232+ return nil , fmt .Errorf ("resource type %s is not supported for revoking" , grant .Principal .Id .ResourceType )
233+ }
234+
235+ splitId := strings .Split (grant .Entitlement .Id , ":" )
236+
237+ dbId , err := strconv .ParseInt (splitId [1 ], 10 , 64 )
238+ if err != nil {
239+ return nil , fmt .Errorf ("unexpected database id: %s" , splitId [1 ])
240+ }
241+
242+ permission := strings .Replace (splitId [2 ], "-grant" , "" , 1 )
243+
244+ database , err := d .client .GetDatabase (ctx , dbId )
245+ if err != nil {
246+ return nil , err
247+ }
248+
249+ user , err := d .client .GetUserPrincipal (ctx , grant .Principal .Id .Resource )
250+ if err != nil {
251+ return nil , err
252+ }
253+
254+ err = d .client .RevokePermissionOnDatabase (ctx , permission , database .Name , user .Name )
255+ if err != nil {
256+ return nil , err
257+ }
258+
259+ l .Debug ("revoked permission" , zap .String ("permission" , permission ), zap .String ("user" , user .Name ), zap .String ("database" , database .Name ))
260+ return nil , nil
261+ }
262+
235263func newDatabaseSyncer (ctx context.Context , c * mssqldb.Client ) * databaseSyncer {
236264 return & databaseSyncer {
237265 resourceType : resourceTypeDatabase ,
0 commit comments