Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions config/transformer/models_list
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#List yang models transformer need to load
openconfig-acl.yang
openconfig-acl-annot.yang
openconfig-sampling-sflow.yang
openconfig-sampling-sflow-annot.yang
openconfig-acl.yang
openconfig-if-aggregate.yang
openconfig-if-ethernet.yang
openconfig-interfaces.yang
openconfig-interfaces-annot.yang
openconfig-if-ip.yang
openconfig-if-aggregate.yang
openconfig-mclag.yang
openconfig-interfaces-annot.yang
openconfig-interfaces.yang
openconfig-mclag-annot.yang
openconfig-mclag.yang
openconfig-sampling-sflow-annot.yang
openconfig-sampling-sflow.yang
openconfig-system-annot.yang
openconfig-vlan.yang
gnsi-authz.yang
gnsi-pathz.yang
Expand Down
34 changes: 31 additions & 3 deletions translib/tlerr/tlerr.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@ Hence, it cannot occur here.
package tlerr

import (
// "fmt"
"errors"
"github.com/Azure/sonic-mgmt-common/cvl"
"github.com/golang/glog"
"golang.org/x/text/language"
"golang.org/x/text/message"
// "errors"
// "strings"
)

var p *message.Printer
Expand Down Expand Up @@ -190,3 +189,32 @@ type TranslibBusy struct {
func (e TranslibBusy) Error() string {
return p.Sprintf("Translib Busy")
}

func IsTranslibRedisClientEntryNotExist(err error) bool {
switch err.(type) {
case *TranslibRedisClientEntryNotExist, TranslibRedisClientEntryNotExist:
return true
}
return false
}

// isDBEntryNotExistError returns `true` if `err` is (or wraps around) an error
// of type `TranslibRedisClientEntryNotExist`.
func isDBEntryNotExistError(err error) bool {
if IsTranslibRedisClientEntryNotExist(err) {
return true
}
pdberr := &TranslibRedisClientEntryNotExist{}
return errors.As(err, &TranslibRedisClientEntryNotExist{}) || errors.As(err, &pdberr)
}

// ErrorSeverity based on `err` calculates the VLOG level.
func ErrorSeverity(err error) glog.Level {
if err == nil {
return 3
}
if isDBEntryNotExistError(err) {
return 3
}
return 0
}
221 changes: 217 additions & 4 deletions translib/transformer/xfmr_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/Azure/sonic-mgmt-common/translib/db"
"github.com/Azure/sonic-mgmt-common/translib/ocbinds"
"github.com/Azure/sonic-mgmt-common/translib/tlerr"
log "github.com/golang/glog"
ygot "github.com/openconfig/ygot/ygot"
)
Expand All @@ -18,7 +19,31 @@ const (
/** Credential Tables **/
CREDENTIALS_TBL = "CREDENTIALS"
CRED_PATHZ_TBL = "CREDENTIALS|PATHZ_POLICY"
CRED_AUTHZ_TBL = "CREDENTIALS|AUTHZ_POLICY"
CERT_TBL = "CREDENTIALS|CERT"
AUTHZ_TBL = "AUTHZ_TABLE"
ACCEPTS = "permitted"
REJECTS = "denied"
cntResult = "cntResult"
tsResult = "tsResult"

/** System Root paths **/
SYSTEM_ROOT = "/openconfig-system:system"

/** Pathz paths **/
GRPC_OC_SERVERS = SYSTEM_ROOT + "/openconfig-system-grpc:grpc-servers"
GRPC_SERVERS = SYSTEM_ROOT + "/grpc-servers"
GRPC_SERVER = GRPC_OC_SERVERS + "/grpc-server"

/** Authz paths **/
AUTHZ_POLICY_COUNTERS = GRPC_SERVER + "/authz-policy-counters"
ALL_AUTHZ = AUTHZ_POLICY_COUNTERS + "/rpcs"
SINGLE_AUTHZ = ALL_AUTHZ + "/rpc"
AUTHZ_STATE = SINGLE_AUTHZ + "/state"
AUTHZ_SUCCESS = AUTHZ_STATE + "/access-accepts"
AUTHZ_SUCCESS_TIMESTAMP = AUTHZ_STATE + "/last-access-accept"
AUTHZ_FAILED = AUTHZ_STATE + "/access-rejects"
AUTHZ_FAILED_TIMESTAMP = AUTHZ_STATE + "/last-access-reject"
)

type sshState struct {
Expand Down Expand Up @@ -46,6 +71,8 @@ func init() {
XlateFuncBind("DbToYang_grpc_server_key_xfmr", DbToYang_grpc_server_key_xfmr)
XlateFuncBind("DbToYang_ssh_server_state_xfmr", DbToYang_ssh_server_state_xfmr)
XlateFuncBind("Subscribe_ssh_server_state_xfmr", Subscribe_ssh_server_state_xfmr)
XlateFuncBind("DbToYang_authz_policy_xfmr", DbToYang_authz_policy_xfmr)
XlateFuncBind("Subscribe_authz_policy_xfmr", Subscribe_authz_policy_xfmr)
}

type grpcState struct {
Expand Down Expand Up @@ -101,6 +128,15 @@ var Subscribe_ssh_server_state_xfmr SubTreeXfmrSubscribe = func(inParams XfmrSub
nOpts: &notificationOpts{mInterval: 0, pType: OnChange},
}, nil
}
var Subscribe_authz_policy_xfmr SubTreeXfmrSubscribe = func(inParams XfmrSubscInParams) (XfmrSubscOutParams, error) {
log.V(3).Infof("Subscribe_authz_policy_xfmr:%s", inParams.requestURI)
return XfmrSubscOutParams{
dbDataMap: RedisDbSubscribeMap{
db.StateDB: {"CREDENTIALS": {"AUTHZ_POLICY|gnxi": {}}}},
onChange: OnchangeEnable,
nOpts: &notificationOpts{mInterval: 0, pType: OnChange},
}, nil
}

var DbToYang_ssh_server_state_xfmr SubTreeXfmrDbToYang = func(inParams XfmrParams) error {
var state sshState
Expand Down Expand Up @@ -156,10 +192,38 @@ var DbToYang_ssh_server_state_xfmr SubTreeXfmrDbToYang = func(inParams XfmrParam
sysObj.SshServer.State.Counters.AccessRejects = &state.counters.accessRejects
sysObj.SshServer.State.Counters.LastAccessAccept = &state.counters.lastAccessAccept
sysObj.SshServer.State.Counters.LastAccessReject = &state.counters.lastAccessReject
return nil
}
var DbToYang_authz_policy_xfmr SubTreeXfmrDbToYang = func(inParams XfmrParams) error {
var state certData

table, err := inParams.dbs[inParams.curDb].GetEntry(&db.TableSpec{Name: CRED_AUTHZ_TBL}, db.Key{Comp: []string{GNXI_ID}})
if err != nil {
log.V(3).Infof("Failed to read from StateDB: %v", inParams.table)
return err
}

state.version = table.Get("authz_version")
time := table.Get("authz_created_on")
if state.created, err = strconv.ParseUint(time, 10, 64); err != nil && time != "" {
log.V(3).Infof("Couldn't find authz_created_on: %v", err)
}

sysObj := getAppRootObject(inParams)
ygot.BuildEmptyTree(sysObj.Aaa.Authorization.State)

sysObj.Aaa.Authorization.State.GrpcAuthzPolicyCreatedOn = &state.created
sysObj.Aaa.Authorization.State.GrpcAuthzPolicyVersion = &state.version

return nil
}

var DbToYang_grpc_server_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) {
log.V(3).Info("DbToYang_grpc_server_key_xfmr root, uri: ", inParams.ygRoot, inParams.uri)

return map[string]interface{}{"name": NewPathInfo(inParams.uri).Var("name")}, nil
}

var Subscribe_grpc_server_xfmr SubTreeXfmrSubscribe = func(inParams XfmrSubscInParams) (XfmrSubscOutParams, error) {
pathInfo := NewPathInfo(inParams.uri)
serverName := pathInfo.Var("name")
Expand Down Expand Up @@ -198,14 +262,20 @@ var Subscribe_grpc_server_xfmr SubTreeXfmrSubscribe = func(inParams XfmrSubscInP
result.onChange = OnchangeEnable
result.nOpts = &notificationOpts{mInterval: 60, pType: Sample}
}

return result, nil
}

var DbToYang_grpc_server_xfmr SubTreeXfmrDbToYang = func(inParams XfmrParams) error {
pathInfo := NewPathInfo(inParams.uri)
serverNames := []string{pathInfo.Var("name")}
targetUriPath, err := getYangPathFromUri(pathInfo.Path)
if err != nil {
log.V(0).Infof("Error Parsing Uri Path, err: %v", err)
}
if log.V(3) {
log.Info("SubtreeXfmrFunc - Uri SYS AUTH: ", inParams.uri)
log.Info("TARGET URI PATH SYS AUTH:", targetUriPath)
log.Info("names:", serverNames)
}
stateDb := inParams.dbs[db.StateDB]
Expand Down Expand Up @@ -289,13 +359,156 @@ var DbToYang_grpc_server_xfmr SubTreeXfmrDbToYang = func(inParams XfmrParams) er
serverObj.State.GnmiPathzPolicyCreatedOn = &state.pathzCreated
serverObj.State.GnmiPathzPolicyVersion = &state.pathzVersion

}
// Authz counter
authzTables, err := stateDb.GetTable(&db.TableSpec{Name: AUTHZ_TBL})
if err != nil {
log.V(tlerr.ErrorSeverity(err)).Infof("getAuthzPolicyCounter failed to get AUTHZ_TBL, err: %v", err)
return err
}

rpcString := pathInfo.Var("name#2")
rpcStrings := []string{rpcString}

if rpcString == "" || rpcString == "*" {
rpcStrings = []string{}
rpcStrings, err = getAllRpcs(authzTables, serverName)
if err != nil {
log.V(tlerr.ErrorSeverity(err)).Infof("Failed get all authz rpcs, err: %v", err)
return err
}
}

ygot.BuildEmptyTree(serverObj.AuthzPolicyCounters)
for _, rpcString := range rpcStrings {
service, rpc, err := getServiceRpc(rpcString)
if err != nil {
log.V(0).Infof("invalid RPC method %s", rpcString)
continue
}

authzPolicyData := getAuthzPolicyCounter(authzTables, serverName, rpcString)
rpcObj, ok := serverObj.AuthzPolicyCounters.Rpcs.Rpc[rpcString]
if !ok {
rpcObj, err = serverObj.AuthzPolicyCounters.Rpcs.NewRpc(rpcString)
if err != nil {
log.V(0).Infof("serverObj.AuthzPolicyCounters.Rpcs.NewRpc(%v) failed: %v", rpcString, err)
continue
}
}
ygot.BuildEmptyTree(rpcObj)

// If targetUriPath is a parent AUTHZ_STATE, i.e.root path, all counters and timestamps should be returned
allAuthzCounter := strings.HasPrefix(AUTHZ_STATE, targetUriPath) || targetUriPath == GRPC_OC_SERVERS

tmpCnt := make(map[string]*uint64)
tmpTs := make(map[string]*uint64)
if cnt, ok := authzPolicyData[cntResult]; ok {
tmpCnt = cnt
}
if ts, ok := authzPolicyData[tsResult]; ok {
tmpTs = ts
}
// Handle root paths here.
if allAuthzCounter {
ygot.BuildEmptyTree(rpcObj.State)
rpcObj.State.AccessAccepts = tmpCnt["*|"+serverName+"|"+service+"|"+rpc+"|"+ACCEPTS]
rpcObj.State.LastAccessAccept = tmpTs["*|"+serverName+"|"+service+"|"+rpc+"|"+ACCEPTS]
rpcObj.State.AccessRejects = tmpCnt["*|"+serverName+"|"+service+"|"+rpc+"|"+REJECTS]
rpcObj.State.LastAccessReject = tmpTs["*|"+serverName+"|"+service+"|"+rpc+"|"+REJECTS]

} else {
// Handle leaf paths here.
switch targetUriPath {
case AUTHZ_SUCCESS:
rpcObj.State.AccessAccepts = tmpCnt["*|"+serverName+"|"+service+"|"+rpc+"|"+ACCEPTS]
case AUTHZ_SUCCESS_TIMESTAMP:
rpcObj.State.LastAccessAccept = tmpTs["*|"+serverName+"|"+service+"|"+rpc+"|"+ACCEPTS]
case AUTHZ_FAILED:
rpcObj.State.AccessRejects = tmpCnt["*|"+serverName+"|"+service+"|"+rpc+"|"+REJECTS]
case AUTHZ_FAILED_TIMESTAMP:
rpcObj.State.LastAccessReject = tmpTs["*|"+serverName+"|"+service+"|"+rpc+"|"+REJECTS]
}
}
}
}
return nil
}

var DbToYang_grpc_server_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) {
log.V(3).Info("DbToYang_grpc_server_key_xfmr root, uri: ", inParams.ygRoot, inParams.uri)
func getAuthzPolicyCounter(authzTables db.Table, server string, rpcString string) map[string]map[string]*uint64 {
cntMap := make(map[string]*uint64)
tsMap := make(map[string]*uint64)

return map[string]interface{}{"name": NewPathInfo(inParams.uri).Var("name")}, nil
for _, oper := range []string{ACCEPTS, REJECTS} {
var service string
var rpc string
service, rpc, err := getServiceRpc(rpcString)
if err != nil {
log.V(0).Infof("invalid RPC method %s", rpcString)
continue
}

pattern := "*|" + server + "|" + service + "|" + rpc + "|" + oper
key := db.NewKey(server, service, rpc, oper)

// Sum the data collected
value, err := authzTables.GetEntry(*key)
if err != nil {
log.V(tlerr.ErrorSeverity(err)).Infof("Cannot get value from %v table for %v, err: %v", AUTHZ_TBL, key, err)
continue
}

c := value.Get("count")
if c != "" {
if dbCnt, err := strconv.ParseUint(c, 10, 64); err == nil {
cntMap[pattern] = &dbCnt
} else {
log.V(tlerr.ErrorSeverity(err)).Infof("Failed to convert counters from DB for authz, err: %v", err)
}
}

ts := value.Get("timestamp")
if ts != "" {
if dbTs, err := strconv.ParseUint(ts, 10, 64); err == nil {
tsMap[pattern] = &dbTs
} else {
log.V(tlerr.ErrorSeverity(err)).Infof("Failed to convert timestamp for counters from DB for authz, err: %v", err)
}
}
}
return map[string]map[string]*uint64{cntResult: cntMap, tsResult: tsMap}
}

func getServiceRpc(rpcString string) (string, string, error) {
strs := strings.Split(rpcString, "/")
if len(strs) == 3 {
return strs[1], strs[2], nil
}

return "", "", errors.New("invalid RPC method " + rpcString)
}

func getAllRpcs(authzTables db.Table, server string) ([]string, error) {
var res []string
check := make(map[string]bool)
authzTableKeys, err := authzTables.GetKeys()
if err != nil {
log.V(tlerr.ErrorSeverity(err)).Infof("Cannot get all keys from %v table, err: %v", AUTHZ_TBL, err)
return []string{}, err
}
for _, authzTableKey := range authzTableKeys {
if len(authzTableKey.Comp) != 4 {
log.V(3).Infof("invalid number of Comps for authzTableKey %v.", authzTableKey)
continue
}
if authzTableKey.Comp[0] != server {
continue
}
key := "/" + authzTableKey.Comp[1] + "/" + authzTableKey.Comp[2]
if val, ok := check[key]; !ok || !val {
res = append(res, key)
check[key] = true
}
}

return res, nil
}