Skip to content

Commit

Permalink
vcsim: add ssoadmin user and group management
Browse files Browse the repository at this point in the history
The ssoadmin endpoint is now used for authentication for both SOAP and REST endpoints.
Previous behavior is retained:
- By default, any non-empty username + password is authenticated
- If vcsim '-username' and '-password' flags are given, only those credentials can be used for authentication

Additional users can be added via the ssoadmin APIs or using govc for example:

  % govc sso.user.create -p password govc

Closes vmware#2852
  • Loading branch information
dougm committed Mar 18, 2023
1 parent c7b7225 commit c62983f
Show file tree
Hide file tree
Showing 5 changed files with 711 additions and 31 deletions.
84 changes: 84 additions & 0 deletions govc/test/sso.bats
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,87 @@ load test_helper
assert_matches "Local OS"
assert_matches "ActiveDirectory"
}

@test "sso.user" {
vcsim_env

run govc sso.user.ls
assert_success

run govc sso.user.create -p password govc
assert_success

run govc sso.user.ls
assert_success
assert_matches govc

run govc sso.user.ls -s
assert_success ""

run govc sso.user.create -p password govc
assert_failure # duplicate name

run govc sso.user.update -p newpassword govc
assert_success

run govc sso.user.rm govc
assert_success

run govc sso.user.rm govc
assert_failure # does not exist

run govc sso.user.create -C dummy-cert govc
assert_success

run govc sso.user.update -C new-cert govc
assert_success

run govc sso.user.ls -s
assert_success
assert_matches govc
}

@test "sso.group" {
vcsim_env

run govc sso.group.ls
assert_success

run govc sso.group.create bats
assert_success

run govc sso.group.create -d "govc CLI" govc
assert_success

run govc sso.group.ls
assert_success
assert_matches "govc CLI"

run govc sso.group.update -d "govmomi/govc CLI" govc
assert_success
run govc sso.group.ls
assert_success
assert_matches "govmomi/govc CLI"

run govc sso.group.update -a user govc
assert_success

govc sso.user.id | grep "groups=govc"

run govc sso.group.update -r user govc
assert_success
govc sso.user.id | grep -v "groups=govc"

run govc sso.group.update -g -a govc bats
assert_success

run govc sso.group.ls govc
assert_success
assert_matches bats

run govc sso.group.rm govc
assert_success

run govc sso.group.rm govc
assert_failure # does not exist
}
28 changes: 28 additions & 0 deletions govc/test/vcsim.bats
Original file line number Diff line number Diff line change
Expand Up @@ -421,20 +421,48 @@ EOF
}

@test "vcsim auth" {
vcsim_start

run env GOVC_USERNAME=anybody GOVC_PASSWORD=anything govc ls -u "$(govc env GOVC_URL)"
assert_success

vcsim_stop

vcsim_start -username nobody -password nothing

run govc ls
assert_success

run govc tags.ls
assert_success

run env GOVC_USERNAME=nobody GOVC_PASSWORD=nothing govc ls -u "$(govc env GOVC_URL)"
assert_success

run env GOVC_USERNAME=nobody GOVC_PASSWORD=nothing govc tags.ls -u "$(govc env GOVC_URL)"
assert_success

run govc ls -u "user:pass@$(govc env GOVC_URL)"
assert_failure

run govc tags.ls -u "user:pass@$(govc env GOVC_URL)"
assert_failure

run env GOVC_USERNAME=user GOVC_PASSWORD=pass govc ls -u "$(govc env GOVC_URL)"
assert_failure

run env GOVC_USERNAME=user GOVC_PASSWORD=pass govc tags.ls -u "$(govc env GOVC_URL)"
assert_failure

run govc sso.user.create -p pass user
assert_success

run govc ls -u "user:pass@$(govc env GOVC_URL)"
assert_success

run govc tags.ls -u "user:pass@$(govc env GOVC_URL)"
assert_success

vcsim_stop

dir=$($mktemp --tmpdir -d govc-test-XXXXX 2>/dev/null || $mktemp -d -t govc-test-XXXXX)
Expand Down
25 changes: 14 additions & 11 deletions simulator/session_manager.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*
Copyright (c) 2017-2018 VMware, Inc. All Rights Reserved.
Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
Expand All @@ -20,6 +20,7 @@ import (
"context"
"fmt"
"net/http"
"net/url"
"os"
"reflect"
"strings"
Expand All @@ -41,6 +42,7 @@ type SessionManager struct {

ServiceHostName string
TLSCert func() string
ValidLogin func(*types.Login) bool

sessions map[string]Session
}
Expand Down Expand Up @@ -106,22 +108,23 @@ func (m *SessionManager) putSession(s Session) {
m.sessions[s.Key] = s
}

func (s *SessionManager) validLogin(ctx *Context, req *types.Login) bool {
if ctx.Session != nil {
return false
}
user := ctx.svc.Listen.User
if user == nil || user == DefaultLogin {
func (s *SessionManager) Authenticate(u url.URL, req *types.Login) bool {
if u.User == nil || u.User == DefaultLogin {
return req.UserName != "" && req.Password != ""
}
pass, _ := user.Password()
return req.UserName == user.Username() && req.Password == pass

if s.ValidLogin != nil {
return s.ValidLogin(req)
}

pass, _ := u.User.Password()
return req.UserName == u.User.Username() && req.Password == pass
}

func (s *SessionManager) Login(ctx *Context, req *types.Login) soap.HasFault {
body := new(methods.LoginBody)

if s.validLogin(ctx, req) {
if ctx.Session == nil && s.Authenticate(*ctx.svc.Listen, req) {
body.Res = &types.LoginResponse{
Returnval: createSession(ctx, req.UserName, req.Locale),
}
Expand Down
Loading

0 comments on commit c62983f

Please sign in to comment.