Skip to content
Open
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
1 change: 1 addition & 0 deletions cmd/authctl/group/group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func TestGroupCommand(t *testing.T) {

//nolint:gosec // G204 it's safe to use exec.Command with a variable here
cmd := exec.Command(authctlPath, append([]string{"group"}, tc.args...)...)
cmd.Env = []string{testutils.CoverDirEnv()}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I thought this was addressed already as part of #782 (comment) :)

testutils.CheckCommand(t, cmd, tc.expectedExitCode)
})
}
Expand Down
19 changes: 10 additions & 9 deletions cmd/authctl/group/set-gid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package group_test

import (
"math"
"os"
"os/exec"
"path/filepath"
"strconv"
"testing"

"github.com/canonical/authd/internal/envutils"
"github.com/canonical/authd/internal/testutils"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
Expand All @@ -26,8 +26,10 @@ func TestSetGIDCommand(t *testing.T) {
testutils.WithCurrentUserAsRoot,
)

err := os.Setenv("AUTHD_SOCKET", daemonSocket)
require.NoError(t, err, "Failed to set AUTHD_SOCKET environment variable")
authctlEnv := []string{
"AUTHD_SOCKET=" + daemonSocket,
testutils.CoverDirEnv(),
}

tests := map[string]struct {
args []string
Expand Down Expand Up @@ -69,18 +71,17 @@ func TestSetGIDCommand(t *testing.T) {

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// Copy authctlEnv to avoid modifying the original slice.
authctlEnv := append([]string{}, authctlEnv...)
if tc.authdUnavailable {
origValue := os.Getenv("AUTHD_SOCKET")
err := os.Setenv("AUTHD_SOCKET", "/non-existent")
var err error
authctlEnv, err = envutils.Setenv(authctlEnv, "AUTHD_SOCKET", "/non-existent")
require.NoError(t, err, "Failed to set AUTHD_SOCKET environment variable")
t.Cleanup(func() {
err := os.Setenv("AUTHD_SOCKET", origValue)
require.NoError(t, err, "Failed to restore AUTHD_SOCKET environment variable")
})
}

//nolint:gosec // G204 it's safe to use exec.Command with a variable here
cmd := exec.Command(authctlPath, append([]string{"group"}, tc.args...)...)
cmd.Env = authctlEnv
testutils.CheckCommand(t, cmd, tc.expectedExitCode)
})
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/authctl/internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func NewUserServiceClient() (authd.UserServiceClient, error) {

conn, err := grpc.NewClient(authdSocket, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, fmt.Errorf("failed to connect to authd: %w", err)
return nil, fmt.Errorf("failed to create gRPC client: %w", err)
}

client := authd.NewUserServiceClient(conn)
Expand Down
1 change: 1 addition & 0 deletions cmd/authctl/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func TestRootCommand(t *testing.T) {

//nolint:gosec // G204 it's safe to use exec.Command with a variable here
cmd := exec.Command(authctlPath, tc.args...)
cmd.Env = []string{testutils.CoverDirEnv()}
testutils.CheckCommand(t, cmd, tc.expectedExitCode)
})
}
Expand Down
9 changes: 5 additions & 4 deletions cmd/authctl/user/lock_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package user_test

import (
"os"
"os/exec"
"path/filepath"
"testing"

"github.com/canonical/authd/internal/testutils"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
)

Expand All @@ -20,8 +18,10 @@ func TestUserLockCommand(t *testing.T) {
testutils.WithCurrentUserAsRoot,
)

err := os.Setenv("AUTHD_SOCKET", daemonSocket)
require.NoError(t, err, "Failed to set AUTHD_SOCKET environment variable")
authctlEnv := []string{
"AUTHD_SOCKET=" + daemonSocket,
testutils.CoverDirEnv(),
}

tests := map[string]struct {
args []string
Expand All @@ -38,6 +38,7 @@ func TestUserLockCommand(t *testing.T) {

//nolint:gosec // G204 it's safe to use exec.Command with a variable here
cmd := exec.Command(authctlPath, append([]string{"user"}, tc.args...)...)
cmd.Env = authctlEnv
testutils.CheckCommand(t, cmd, tc.expectedExitCode)
})
}
Expand Down
52 changes: 52 additions & 0 deletions cmd/authctl/user/set-shell.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package user

import (
"context"

"github.com/canonical/authd/cmd/authctl/internal/client"
"github.com/canonical/authd/cmd/authctl/internal/completion"
"github.com/canonical/authd/cmd/authctl/internal/log"
"github.com/canonical/authd/internal/proto/authd"
"github.com/spf13/cobra"
)

var setShellCmd = &cobra.Command{
Use: "set-shell <name> <shell>",
Short: "Set the login shell for a user",
Args: cobra.ExactArgs(2),
ValidArgsFunction: setShellCompletionFunc,
RunE: runSetShell,
}

func runSetShell(cmd *cobra.Command, args []string) error {
name := args[0]
shell := args[1]

svc, err := client.NewUserServiceClient()
if err != nil {
return err
}

resp, err := svc.SetShell(context.Background(), &authd.SetShellRequest{
Name: name,
Shell: shell,
})
if resp == nil {
return err
}

// Print any warnings returned by the server.
for _, warning := range resp.Warnings {
log.Warning(warning)
}

return err
}

func setShellCompletionFunc(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 0 {
return completion.Users(cmd, args, toComplete)
}

return nil, cobra.ShellCompDirectiveNoFileComp
}
49 changes: 49 additions & 0 deletions cmd/authctl/user/set-shell_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package user_test

import (
"os/exec"
"path/filepath"
"testing"

"github.com/canonical/authd/internal/testutils"
"google.golang.org/grpc/codes"
)

func TestSetShellCommand(t *testing.T) {
t.Parallel()

daemonSocket := testutils.StartAuthd(t, daemonPath,
testutils.WithGroupFile(filepath.Join("testdata", "empty.group")),
testutils.WithPreviousDBState("one_user_and_group"),
testutils.WithCurrentUserAsRoot,
)

authctlEnv := []string{
"AUTHD_SOCKET=" + daemonSocket,
testutils.CoverDirEnv(),
}

tests := map[string]struct {
args []string

expectedExitCode int
}{
"Set_shell_success": {args: []string{"set-shell", "user1", "/bin/bash"}, expectedExitCode: 0},

"Error_when_user_does_not_exist": {
args: []string{"set-shell", "invaliduser", "/bin/bash"},
expectedExitCode: int(codes.NotFound),
},
}

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
t.Parallel()

//nolint:gosec // G204 it's safe to use exec.Command with a variable here
cmd := exec.Command(authctlPath, append([]string{"user"}, tc.args...)...)
cmd.Env = authctlEnv
testutils.CheckCommand(t, cmd, tc.expectedExitCode)
})
}
}
20 changes: 10 additions & 10 deletions cmd/authctl/user/set-uid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package user_test

import (
"math"
"os"
"os/exec"
"path/filepath"
"strconv"
"testing"

"github.com/canonical/authd/internal/envutils"
"github.com/canonical/authd/internal/testutils"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
Expand All @@ -19,15 +19,16 @@ func TestSetUIDCommand(t *testing.T) {
// which makes userslocking.WriteLock() return an error immediately when the lock
// is already held - unlike the normal behavior which tries to acquire the lock
// for 15 seconds before returning an error.

daemonSocket := testutils.StartAuthd(t, daemonPath,
testutils.WithGroupFile(filepath.Join("testdata", "empty.group")),
testutils.WithPreviousDBState("one_user_and_group"),
testutils.WithCurrentUserAsRoot,
)

err := os.Setenv("AUTHD_SOCKET", daemonSocket)
require.NoError(t, err, "Failed to set AUTHD_SOCKET environment variable")
authctlEnv := []string{
"AUTHD_SOCKET=" + daemonSocket,
testutils.CoverDirEnv(),
}

tests := map[string]struct {
args []string
Expand Down Expand Up @@ -69,18 +70,17 @@ func TestSetUIDCommand(t *testing.T) {

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
// Copy authctlEnv to avoid modifying the original slice.
authctlEnv := append([]string{}, authctlEnv...)
if tc.authdUnavailable {
origValue := os.Getenv("AUTHD_SOCKET")
err := os.Setenv("AUTHD_SOCKET", "/non-existent")
var err error
authctlEnv, err = envutils.Setenv(authctlEnv, "AUTHD_SOCKET", "/non-existent")
require.NoError(t, err, "Failed to set AUTHD_SOCKET environment variable")
t.Cleanup(func() {
err := os.Setenv("AUTHD_SOCKET", origValue)
require.NoError(t, err, "Failed to restore AUTHD_SOCKET environment variable")
})
}

//nolint:gosec // G204 it's safe to use exec.Command with a variable here
cmd := exec.Command(authctlPath, append([]string{"user"}, tc.args...)...)
cmd.Env = authctlEnv
testutils.CheckCommand(t, cmd, tc.expectedExitCode)
})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Error: user "invaliduser" not found
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Available Commands:
lock Lock (disable) a user managed by authd
unlock Unlock (enable) a user managed by authd
set-uid Set the UID of a user managed by authd
set-shell Set the login shell for a user

Flags:
-h, --help help for user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Available Commands:
lock Lock (disable) a user managed by authd
unlock Unlock (enable) a user managed by authd
set-uid Set the UID of a user managed by authd
set-shell Set the login shell for a user

Flags:
-h, --help help for user
Expand Down
1 change: 1 addition & 0 deletions cmd/authctl/user/testdata/golden/TestUserCommand/Help_flag
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Available Commands:
lock Lock (disable) a user managed by authd
unlock Unlock (enable) a user managed by authd
set-uid Set the UID of a user managed by authd
set-shell Set the login shell for a user

Flags:
-h, --help help for user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Available Commands:
lock Lock (disable) a user managed by authd
unlock Unlock (enable) a user managed by authd
set-uid Set the UID of a user managed by authd
set-shell Set the login shell for a user

Flags:
-h, --help help for user
Expand Down
1 change: 1 addition & 0 deletions cmd/authctl/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ func init() {
UserCmd.AddCommand(lockCmd)
UserCmd.AddCommand(unlockCmd)
UserCmd.AddCommand(setUIDCmd)
UserCmd.AddCommand(setShellCmd)
}
1 change: 1 addition & 0 deletions cmd/authctl/user/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func TestUserCommand(t *testing.T) {

//nolint:gosec // G204 it's safe to use exec.Command with a variable here
cmd := exec.Command(authctlPath, append([]string{"user"}, tc.args...)...)
cmd.Env = []string{testutils.CoverDirEnv()}
testutils.CheckCommand(t, cmd, tc.expectedExitCode)
})
}
Expand Down
1 change: 1 addition & 0 deletions docs/reference/cli/authctl_user.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ authctl user [flags]

* [authctl](authctl.md) - CLI tool to interact with authd
* [authctl user lock](authctl_user_lock.md) - Lock (disable) a user managed by authd
* [authctl user set-shell](authctl_user_set-shell.md) - Set the login shell for a user
* [authctl user set-uid](authctl_user_set-uid.md) - Set the UID of a user managed by authd
* [authctl user unlock](authctl_user_unlock.md) - Unlock (enable) a user managed by authd

18 changes: 18 additions & 0 deletions docs/reference/cli/authctl_user_set-shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## authctl user set-shell

Set the login shell for a user

```
authctl user set-shell <name> <shell> [flags]
```

### Options

```
-h, --help help for set-shell
```

### SEE ALSO

* [authctl user](authctl_user.md) - Commands related to users

1 change: 1 addition & 0 deletions docs/reference/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ authctl_user
authctl_user_lock
authctl_user_unlock
authctl_user_set-uid
authctl_user_set-shell
```

```{toctree}
Expand Down
Loading
Loading