88
99 "github.com/Azure/sonic-mgmt-common/translib/db"
1010 "github.com/Azure/sonic-mgmt-common/translib/ocbinds"
11+ "github.com/Azure/sonic-mgmt-common/translib/tlerr"
1112 log "github.com/golang/glog"
1213 ygot "github.com/openconfig/ygot/ygot"
1314)
@@ -18,7 +19,31 @@ const (
1819 /** Credential Tables **/
1920 CREDENTIALS_TBL = "CREDENTIALS"
2021 CRED_PATHZ_TBL = "CREDENTIALS|PATHZ_POLICY"
22+ CRED_AUTHZ_TBL = "CREDENTIALS|AUTHZ_POLICY"
2123 CERT_TBL = "CREDENTIALS|CERT"
24+ AUTHZ_TBL = "AUTHZ_TABLE"
25+ ACCEPTS = "permitted"
26+ REJECTS = "denied"
27+ cntResult = "cntResult"
28+ tsResult = "tsResult"
29+
30+ /** System Root paths **/
31+ SYSTEM_ROOT = "/openconfig-system:system"
32+
33+ /** Pathz paths **/
34+ GRPC_OC_SERVERS = SYSTEM_ROOT + "/openconfig-system-grpc:grpc-servers"
35+ GRPC_SERVERS = SYSTEM_ROOT + "/grpc-servers"
36+ GRPC_SERVER = GRPC_OC_SERVERS + "/grpc-server"
37+
38+ /** Authz paths **/
39+ AUTHZ_POLICY_COUNTERS = GRPC_SERVER + "/authz-policy-counters"
40+ ALL_AUTHZ = AUTHZ_POLICY_COUNTERS + "/rpcs"
41+ SINGLE_AUTHZ = ALL_AUTHZ + "/rpc"
42+ AUTHZ_STATE = SINGLE_AUTHZ + "/state"
43+ AUTHZ_SUCCESS = AUTHZ_STATE + "/access-accepts"
44+ AUTHZ_SUCCESS_TIMESTAMP = AUTHZ_STATE + "/last-access-accept"
45+ AUTHZ_FAILED = AUTHZ_STATE + "/access-rejects"
46+ AUTHZ_FAILED_TIMESTAMP = AUTHZ_STATE + "/last-access-reject"
2247)
2348
2449type sshState struct {
@@ -46,6 +71,8 @@ func init() {
4671 XlateFuncBind ("DbToYang_grpc_server_key_xfmr" , DbToYang_grpc_server_key_xfmr )
4772 XlateFuncBind ("DbToYang_ssh_server_state_xfmr" , DbToYang_ssh_server_state_xfmr )
4873 XlateFuncBind ("Subscribe_ssh_server_state_xfmr" , Subscribe_ssh_server_state_xfmr )
74+ XlateFuncBind ("DbToYang_authz_policy_xfmr" , DbToYang_authz_policy_xfmr )
75+ XlateFuncBind ("Subscribe_authz_policy_xfmr" , Subscribe_authz_policy_xfmr )
4976}
5077
5178type grpcState struct {
@@ -101,6 +128,15 @@ var Subscribe_ssh_server_state_xfmr SubTreeXfmrSubscribe = func(inParams XfmrSub
101128 nOpts : & notificationOpts {mInterval : 0 , pType : OnChange },
102129 }, nil
103130}
131+ var Subscribe_authz_policy_xfmr SubTreeXfmrSubscribe = func (inParams XfmrSubscInParams ) (XfmrSubscOutParams , error ) {
132+ log .V (3 ).Infof ("Subscribe_authz_policy_xfmr:%s" , inParams .requestURI )
133+ return XfmrSubscOutParams {
134+ dbDataMap : RedisDbSubscribeMap {
135+ db .StateDB : {"CREDENTIALS" : {"AUTHZ_POLICY|gnxi" : {}}}},
136+ onChange : OnchangeEnable ,
137+ nOpts : & notificationOpts {mInterval : 0 , pType : OnChange },
138+ }, nil
139+ }
104140
105141var DbToYang_ssh_server_state_xfmr SubTreeXfmrDbToYang = func (inParams XfmrParams ) error {
106142 var state sshState
@@ -156,10 +192,38 @@ var DbToYang_ssh_server_state_xfmr SubTreeXfmrDbToYang = func(inParams XfmrParam
156192 sysObj .SshServer .State .Counters .AccessRejects = & state .counters .accessRejects
157193 sysObj .SshServer .State .Counters .LastAccessAccept = & state .counters .lastAccessAccept
158194 sysObj .SshServer .State .Counters .LastAccessReject = & state .counters .lastAccessReject
195+ return nil
196+ }
197+ var DbToYang_authz_policy_xfmr SubTreeXfmrDbToYang = func (inParams XfmrParams ) error {
198+ var state certData
199+
200+ table , err := inParams .dbs [inParams .curDb ].GetEntry (& db.TableSpec {Name : CRED_AUTHZ_TBL }, db.Key {Comp : []string {GNXI_ID }})
201+ if err != nil {
202+ log .V (3 ).Infof ("Failed to read from StateDB: %v" , inParams .table )
203+ return err
204+ }
205+
206+ state .version = table .Get ("authz_version" )
207+ time := table .Get ("authz_created_on" )
208+ if state .created , err = strconv .ParseUint (time , 10 , 64 ); err != nil && time != "" {
209+ log .V (3 ).Infof ("Couldn't find authz_created_on: %v" , err )
210+ }
211+
212+ sysObj := getAppRootObject (inParams )
213+ ygot .BuildEmptyTree (sysObj .Aaa .Authorization .State )
214+
215+ sysObj .Aaa .Authorization .State .GrpcAuthzPolicyCreatedOn = & state .created
216+ sysObj .Aaa .Authorization .State .GrpcAuthzPolicyVersion = & state .version
159217
160218 return nil
161219}
162220
221+ var DbToYang_grpc_server_key_xfmr KeyXfmrDbToYang = func (inParams XfmrParams ) (map [string ]interface {}, error ) {
222+ log .V (3 ).Info ("DbToYang_grpc_server_key_xfmr root, uri: " , inParams .ygRoot , inParams .uri )
223+
224+ return map [string ]interface {}{"name" : NewPathInfo (inParams .uri ).Var ("name" )}, nil
225+ }
226+
163227var Subscribe_grpc_server_xfmr SubTreeXfmrSubscribe = func (inParams XfmrSubscInParams ) (XfmrSubscOutParams , error ) {
164228 pathInfo := NewPathInfo (inParams .uri )
165229 serverName := pathInfo .Var ("name" )
@@ -198,14 +262,20 @@ var Subscribe_grpc_server_xfmr SubTreeXfmrSubscribe = func(inParams XfmrSubscInP
198262 result .onChange = OnchangeEnable
199263 result .nOpts = & notificationOpts {mInterval : 60 , pType : Sample }
200264 }
265+
201266 return result , nil
202267}
203268
204269var DbToYang_grpc_server_xfmr SubTreeXfmrDbToYang = func (inParams XfmrParams ) error {
205270 pathInfo := NewPathInfo (inParams .uri )
206271 serverNames := []string {pathInfo .Var ("name" )}
272+ targetUriPath , err := getYangPathFromUri (pathInfo .Path )
273+ if err != nil {
274+ log .V (0 ).Infof ("Error Parsing Uri Path, err: %v" , err )
275+ }
207276 if log .V (3 ) {
208277 log .Info ("SubtreeXfmrFunc - Uri SYS AUTH: " , inParams .uri )
278+ log .Info ("TARGET URI PATH SYS AUTH:" , targetUriPath )
209279 log .Info ("names:" , serverNames )
210280 }
211281 stateDb := inParams .dbs [db .StateDB ]
@@ -289,13 +359,156 @@ var DbToYang_grpc_server_xfmr SubTreeXfmrDbToYang = func(inParams XfmrParams) er
289359 serverObj .State .GnmiPathzPolicyCreatedOn = & state .pathzCreated
290360 serverObj .State .GnmiPathzPolicyVersion = & state .pathzVersion
291361
292- }
362+ // Authz counter
363+ authzTables , err := stateDb .GetTable (& db.TableSpec {Name : AUTHZ_TBL })
364+ if err != nil {
365+ log .V (tlerr .ErrorSeverity (err )).Infof ("getAuthzPolicyCounter failed to get AUTHZ_TBL, err: %v" , err )
366+ return err
367+ }
368+
369+ rpcString := pathInfo .Var ("name#2" )
370+ rpcStrings := []string {rpcString }
371+
372+ if rpcString == "" || rpcString == "*" {
373+ rpcStrings = []string {}
374+ rpcStrings , err = getAllRpcs (authzTables , serverName )
375+ if err != nil {
376+ log .V (tlerr .ErrorSeverity (err )).Infof ("Failed get all authz rpcs, err: %v" , err )
377+ return err
378+ }
379+ }
380+
381+ ygot .BuildEmptyTree (serverObj .AuthzPolicyCounters )
382+ for _ , rpcString := range rpcStrings {
383+ service , rpc , err := getServiceRpc (rpcString )
384+ if err != nil {
385+ log .V (0 ).Infof ("invalid RPC method %s" , rpcString )
386+ continue
387+ }
388+
389+ authzPolicyData := getAuthzPolicyCounter (authzTables , serverName , rpcString )
390+ rpcObj , ok := serverObj .AuthzPolicyCounters .Rpcs .Rpc [rpcString ]
391+ if ! ok {
392+ rpcObj , err = serverObj .AuthzPolicyCounters .Rpcs .NewRpc (rpcString )
393+ if err != nil {
394+ log .V (0 ).Infof ("serverObj.AuthzPolicyCounters.Rpcs.NewRpc(%v) failed: %v" , rpcString , err )
395+ continue
396+ }
397+ }
398+ ygot .BuildEmptyTree (rpcObj )
399+
400+ // If targetUriPath is a parent AUTHZ_STATE, i.e.root path, all counters and timestamps should be returned
401+ allAuthzCounter := strings .HasPrefix (AUTHZ_STATE , targetUriPath ) || targetUriPath == GRPC_OC_SERVERS
293402
403+ tmpCnt := make (map [string ]* uint64 )
404+ tmpTs := make (map [string ]* uint64 )
405+ if cnt , ok := authzPolicyData [cntResult ]; ok {
406+ tmpCnt = cnt
407+ }
408+ if ts , ok := authzPolicyData [tsResult ]; ok {
409+ tmpTs = ts
410+ }
411+ // Handle root paths here.
412+ if allAuthzCounter {
413+ ygot .BuildEmptyTree (rpcObj .State )
414+ rpcObj .State .AccessAccepts = tmpCnt ["*|" + serverName + "|" + service + "|" + rpc + "|" + ACCEPTS ]
415+ rpcObj .State .LastAccessAccept = tmpTs ["*|" + serverName + "|" + service + "|" + rpc + "|" + ACCEPTS ]
416+ rpcObj .State .AccessRejects = tmpCnt ["*|" + serverName + "|" + service + "|" + rpc + "|" + REJECTS ]
417+ rpcObj .State .LastAccessReject = tmpTs ["*|" + serverName + "|" + service + "|" + rpc + "|" + REJECTS ]
418+
419+ } else {
420+ // Handle leaf paths here.
421+ switch targetUriPath {
422+ case AUTHZ_SUCCESS :
423+ rpcObj .State .AccessAccepts = tmpCnt ["*|" + serverName + "|" + service + "|" + rpc + "|" + ACCEPTS ]
424+ case AUTHZ_SUCCESS_TIMESTAMP :
425+ rpcObj .State .LastAccessAccept = tmpTs ["*|" + serverName + "|" + service + "|" + rpc + "|" + ACCEPTS ]
426+ case AUTHZ_FAILED :
427+ rpcObj .State .AccessRejects = tmpCnt ["*|" + serverName + "|" + service + "|" + rpc + "|" + REJECTS ]
428+ case AUTHZ_FAILED_TIMESTAMP :
429+ rpcObj .State .LastAccessReject = tmpTs ["*|" + serverName + "|" + service + "|" + rpc + "|" + REJECTS ]
430+ }
431+ }
432+ }
433+ }
294434 return nil
295435}
296436
297- var DbToYang_grpc_server_key_xfmr KeyXfmrDbToYang = func (inParams XfmrParams ) (map [string ]interface {}, error ) {
298- log .V (3 ).Info ("DbToYang_grpc_server_key_xfmr root, uri: " , inParams .ygRoot , inParams .uri )
437+ func getAuthzPolicyCounter (authzTables db.Table , server string , rpcString string ) map [string ]map [string ]* uint64 {
438+ cntMap := make (map [string ]* uint64 )
439+ tsMap := make (map [string ]* uint64 )
299440
300- return map [string ]interface {}{"name" : NewPathInfo (inParams .uri ).Var ("name" )}, nil
441+ for _ , oper := range []string {ACCEPTS , REJECTS } {
442+ var service string
443+ var rpc string
444+ service , rpc , err := getServiceRpc (rpcString )
445+ if err != nil {
446+ log .V (0 ).Infof ("invalid RPC method %s" , rpcString )
447+ continue
448+ }
449+
450+ pattern := "*|" + server + "|" + service + "|" + rpc + "|" + oper
451+ key := db .NewKey (server , service , rpc , oper )
452+
453+ // Sum the data collected
454+ value , err := authzTables .GetEntry (* key )
455+ if err != nil {
456+ log .V (tlerr .ErrorSeverity (err )).Infof ("Cannot get value from %v table for %v, err: %v" , AUTHZ_TBL , key , err )
457+ continue
458+ }
459+
460+ c := value .Get ("count" )
461+ if c != "" {
462+ if dbCnt , err := strconv .ParseUint (c , 10 , 64 ); err == nil {
463+ cntMap [pattern ] = & dbCnt
464+ } else {
465+ log .V (tlerr .ErrorSeverity (err )).Infof ("Failed to convert counters from DB for authz, err: %v" , err )
466+ }
467+ }
468+
469+ ts := value .Get ("timestamp" )
470+ if ts != "" {
471+ if dbTs , err := strconv .ParseUint (ts , 10 , 64 ); err == nil {
472+ tsMap [pattern ] = & dbTs
473+ } else {
474+ log .V (tlerr .ErrorSeverity (err )).Infof ("Failed to convert timestamp for counters from DB for authz, err: %v" , err )
475+ }
476+ }
477+ }
478+ return map [string ]map [string ]* uint64 {cntResult : cntMap , tsResult : tsMap }
479+ }
480+
481+ func getServiceRpc (rpcString string ) (string , string , error ) {
482+ strs := strings .Split (rpcString , "/" )
483+ if len (strs ) == 3 {
484+ return strs [1 ], strs [2 ], nil
485+ }
486+
487+ return "" , "" , errors .New ("invalid RPC method " + rpcString )
488+ }
489+
490+ func getAllRpcs (authzTables db.Table , server string ) ([]string , error ) {
491+ var res []string
492+ check := make (map [string ]bool )
493+ authzTableKeys , err := authzTables .GetKeys ()
494+ if err != nil {
495+ log .V (tlerr .ErrorSeverity (err )).Infof ("Cannot get all keys from %v table, err: %v" , AUTHZ_TBL , err )
496+ return []string {}, err
497+ }
498+ for _ , authzTableKey := range authzTableKeys {
499+ if len (authzTableKey .Comp ) != 4 {
500+ log .V (3 ).Infof ("invalid number of Comps for authzTableKey %v." , authzTableKey )
501+ continue
502+ }
503+ if authzTableKey .Comp [0 ] != server {
504+ continue
505+ }
506+ key := "/" + authzTableKey .Comp [1 ] + "/" + authzTableKey .Comp [2 ]
507+ if val , ok := check [key ]; ! ok || ! val {
508+ res = append (res , key )
509+ check [key ] = true
510+ }
511+ }
512+
513+ return res , nil
301514}
0 commit comments