Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restconf Authorization Failed when trying to POST, PUT, PATCH, DELETE #185

Open
Saran2110 opened this issue Jan 13, 2024 · 1 comment
Open
Assignees

Comments

@Saran2110
Copy link

Saran2110 commented Jan 13, 2024

Description:

Authorization Error in SONIC Restconf while trying to POST, PUT, PATCH, DELETE with user in admin group.
To do GET there is no need of admin permissions but for POST, PUT, PATCH, DELETE user must be in admin group.
But with current code admin group user also getting Not an admin Error.

Steps to reproduce the issue:

  1. In swagger ui or curl and try POST/PUT/PATCH/DELETE with default user.
  2. Create new user add that user in admin group and try with that user.
    E.g.,
    To Try with default user,
    curl -X POST https://192.168.86.43/restconf/data/openconfig-system:system/ntp -H "accept: application/yang-data+json" --user admin:admin123 -H "Content-Type: application/yang-data+json" -d "{ "openconfig-system:servers": { "server": [ { "address": "1.1.1.1", "config": { "address": "1.1.1.1" } } ] }}" -v -k
    To Try with new user,
    Create user test - sudo useradd test
    Set password - sudo passwd test
    Add to admin group - sudo usermod -a -G admin test
    curl -X POST https://192.168.86.43/restconf/data/openconfig-system:system/ntp -H "accept: application/yang-data+json" --user test:admin123 -H "Content-Type: application/yang-data+json" -d "{ "openconfig-system:servers": { "server": [ { "address": "1.1.1.1", "config": { "address": "1.1.1.1" } } ] }}" -v -k
    (If needed) Delete from admin group - sudo deluser test admin

Describe the results you received:

Unable to do any POST, PUT, PATCH, DELETE.
"ietf-restconf:errors": {
"error": [
{
"error-type": "protocol",
"error-tag": "access-denied",
"error-message": "Not an admin user"
}
]
}

Logs:
Jan 11 12:44:19.310522 sonic INFO mgmt-framework#/supervisord: rest-server I1218 12:44:19.307388 2171 pamAuth.go:107] [REST-3] Received user=admin
Jan 11 12:44:20.008721 sonic INFO mgmt-framework#/supervisord: rest-server I1218 12:44:20.006653 2171 pamAuth.go:135] [REST-3] Authentication passed. user=admin
Jan 11 12:44:20.014797 sonic INFO mgmt-framework#/supervisord: rest-server I1218 12:44:20.010018 2171 pamAuth.go:74] IsAdminGroup username = admin
Jan 11 12:44:20.015757 sonic INFO mgmt-framework#/supervisord: rest-server I1218 12:44:20.010572 2171 pamAuth.go:76] IsAdminGroup err = user: unknown user admin
Jan 11 12:44:20.015757 sonic INFO mgmt-framework#/supervisord: rest-server I1218 12:44:20.010668 2171 pamAuth.go:78] IsAdminGroup 1st IF Check
Jan 11 12:44:20.015757 sonic INFO mgmt-framework#/supervisord: rest-server W1218 12:44:20.010697 2171 pamAuth.go:139] [REST-3] Not an admin; cannot allow POST
Describe the results you expected:
POST, PUT, PATCH, DELETE should work fine.

Reason for the issue:

https://github.com/sonic-net/sonic-mgmt-framework/blob/master/rest/server/pamAuth.go file contains IsAdminGroup Function.
func IsAdminGroup(username string) bool {
usr, err := user.Lookup(username)
if err != nil {
return false
}
gids, err := usr.GroupIds()
if err != nil {
return false
}
glog.V(2).Infof("User:%s, groups=%s", username, gids)
admin, err := user.Lookup("admin")
if err != nil {
return false
}
for _, x := range gids {
if x == admin.Gid {
return true
}
}
return false
}
In which they are checking if the user present in /etc/passwd.
This is the Lookup function that used in isAdminGroup function - https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:src/os/user/lookup.go;l=39
// Lookup looks up a user by username. If the user cannot be found, the
// returned error is of type UnknownUserError.
func Lookup(username string) (*User, error) {
if u, err := Current(); err == nil && u.Username == username {
return u, err
}
return lookupUser(username)
}

const (
userFile = "/etc/passwd"
groupFile = "/etc/group"
)

func lookupUser(username string) (*User, error) {
f, err := os.Open(userFile)
if err != nil {
return nil, err
}
defer f.Close()
return findUsername(username, f)
}
Rest server running in docker-sonic-mgmt-framework. Docker and Host having separate /etc/passwd. When checking by adding logs we found that user is not available inside Docker’s /etc/passwd, it’s available only on Host’s /etc/passwd.
But in this Authorization code they are using Docker's /etc/passwd file to validation, Because of that for valid user also getting "Not an admin user" error for POST, PUT, PATCH, DELETE.

Solution we have tried:

We have tried by taking dockers/docker-sonic-mgmt-framework/Dockerfile.j2 from sonic-net/sonic-buildimage#6148 , which is working.
But it’s not available in Master as the changes are reverted in sonic-net/sonic-buildimage#9375
There is already SSH dial is added for Authentication in PAMAuthenAndAuthor function.
We have used same session and running ‘id -Gn’ command to check whether the user is from admin group because POST, PUT, PATCH, DELETE should be allowed only for users in admin group.

@volodymyrsamotiy
Copy link

Should be triaged in different subgroup.
@prsunny will help to move this issue to sonic-gnmi repo for further triage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants