Skip to content

Commit

Permalink
handle sudoer arg in postCreateUser, AddExtraUser
Browse files Browse the repository at this point in the history
  • Loading branch information
mwhudson committed Aug 10, 2016
1 parent 577eeed commit d1ed9bc
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 14 deletions.
11 changes: 7 additions & 4 deletions daemon/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1415,7 +1415,7 @@ func abortChange(c *Command, r *http.Request, user *auth.UserState) Response {
var (
postCreateUserUcrednetGetUID = ucrednetGetUID
storeUserInfo = store.UserInfo
osutilAddExtraSudoUser = osutil.AddExtraSudoUser
osutilAddExtraUser = osutil.AddExtraUser
)

func postCreateUser(c *Command, r *http.Request, user *auth.UserState) Response {
Expand All @@ -1428,7 +1428,8 @@ func postCreateUser(c *Command, r *http.Request, user *auth.UserState) Response
}

var createData struct {
EMail string `json:"email"`
EMail string `json:"email"`
Sudoer bool `json:"sudoer"`
}

decoder := json.NewDecoder(r.Body)
Expand All @@ -1449,14 +1450,16 @@ func postCreateUser(c *Command, r *http.Request, user *auth.UserState) Response
}

gecos := fmt.Sprintf("%s,%s", createData.EMail, v.OpenIDIdentifier)
if err := osutilAddExtraSudoUser(v.Username, v.SSHKeys, gecos); err != nil {
if err := osutilAddExtraUser(v.Username, v.SSHKeys, gecos, createData.Sudoer); err != nil {
return BadRequest("cannot create user %s: %s", v.Username, err)
}

var createResponseData struct {
Username string `json:"username"`
Username string `json:"username"`
SshKeyCount int `json:"ssh_key_count"`
}
createResponseData.Username = v.Username
createResponseData.SshKeyCount = len(v.SSHKeys)

return SyncResponse(createResponseData, nil)
}
Expand Down
5 changes: 3 additions & 2 deletions daemon/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3111,18 +3111,19 @@ func (s *apiSuite) TestPostCreateUser(c *check.C) {
OpenIDIdentifier: "xxyyzz",
}, nil
}
osutilAddExtraSudoUser = func(username string, sshKeys []string, gecos string) error {
osutilAddExtraUser = func(username string, sshKeys []string, gecos string, sudoer bool) error {
c.Check(username, check.Equals, "karl")
c.Check(sshKeys, check.DeepEquals, []string{"ssh1", "ssh2"})
c.Check(gecos, check.Equals, "popper@lse.ac.uk,xxyyzz")
c.Check(sudoer, check.Equals, false)
return nil
}

postCreateUserUcrednetGetUID = func(string) (uint32, error) {
return 0, nil
}
defer func() {
osutilAddExtraSudoUser = osutil.AddExtraSudoUser
osutilAddExtraUser = osutil.AddExtraUser
postCreateUserUcrednetGetUID = ucrednetGetUID
}()

Expand Down
12 changes: 7 additions & 5 deletions osutil/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ var sudoersTemplate = `
%[1]s ALL=(ALL) NOPASSWD:ALL
`

func AddExtraSudoUser(name string, sshKeys []string, gecos string) error {
func AddExtraUser(name string, sshKeys []string, gecos string, sudoer bool) error {
// we check the (user)name ourselves, adduser is a bit too
// strict (i.e. no `.`) - this regexp is in sync with that SSO
// allows as valid usernames
Expand All @@ -60,10 +60,12 @@ func AddExtraSudoUser(name string, sshKeys []string, gecos string) error {
return fmt.Errorf("adduser failed with %s: %s", err, output)
}

// Must escape "." as files containing it are ignored in sudoers.d.
sudoersFile := filepath.Join(sudoersDotD, "create-user-"+strings.Replace(name, ".", "%2E", -1))
if err := AtomicWriteFile(sudoersFile, []byte(fmt.Sprintf(sudoersTemplate, name)), 0400, 0); err != nil {
return fmt.Errorf("cannot create file under sudoers.d: %s", err)
if sudoer {
// Must escape "." as files containing it are ignored in sudoers.d.
sudoersFile := filepath.Join(sudoersDotD, "create-user-"+strings.Replace(name, ".", "%2E", -1))
if err := AtomicWriteFile(sudoersFile, []byte(fmt.Sprintf(sudoersTemplate, name)), 0400, 0); err != nil {
return fmt.Errorf("cannot create file under sudoers.d: %s", err)
}
}

u, err := userLookup(name)
Expand Down
17 changes: 14 additions & 3 deletions osutil/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,18 @@ func (s *createUserSuite) TestAddExtraSudoUser(c *check.C) {
mockAddUser := testutil.MockCommand(c, "adduser", "true")
defer mockAddUser.Restore()

err := osutil.AddExtraSudoUser("karl.sagan", []string{"ssh-key1", "ssh-key2"}, "my gecos")
err := osutil.AddExtraUser("karl.sagan", []string{"ssh-key1", "ssh-key2"}, "my gecos", false)
c.Assert(err, check.IsNil)

c.Check(mockAddUser.Calls(), check.DeepEquals, [][]string{
{"adduser", "--force-badname", "--gecos", "my gecos", "--extrausers", "--disabled-password", "karl.sagan"},
})
fs, _ := filepath.Glob(filepath.Join(mockSudoers, "*"))
c.Assert(fs, check.HasLen, 0)

mockAddUser.ForgetCalls()

err = osutil.AddExtraUser("karl.sagan", []string{"ssh-key1", "ssh-key2"}, "my gecos", true)
c.Assert(err, check.IsNil)

c.Check(mockAddUser.Calls(), check.DeepEquals, [][]string{
Expand All @@ -68,7 +79,7 @@ func (s *createUserSuite) TestAddExtraSudoUser(c *check.C) {
c.Assert(err, check.IsNil)
c.Check(string(sshKeys), check.Equals, "ssh-key1\nssh-key2")

fs, _ := filepath.Glob(filepath.Join(mockSudoers, "*"))
fs, _ = filepath.Glob(filepath.Join(mockSudoers, "*"))
c.Assert(fs, check.HasLen, 1)
c.Assert(filepath.Base(fs[0]), check.Equals, "create-user-karl%2Esagan")
bs, err := ioutil.ReadFile(fs[0])
Expand All @@ -82,6 +93,6 @@ karl.sagan ALL=(ALL) NOPASSWD:ALL
}

func (s *createUserSuite) TestAddExtraSudoUserInvalid(c *check.C) {
err := osutil.AddExtraSudoUser("k!", nil, "my gecos")
err := osutil.AddExtraUser("k!", nil, "my gecos", false)
c.Assert(err, check.ErrorMatches, `cannot add user "k!": name contains invalid characters`)
}

0 comments on commit d1ed9bc

Please sign in to comment.