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

Add secret support to podman login #19200

Merged
merged 2 commits into from
Jul 13, 2023
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
34 changes: 33 additions & 1 deletion cmd/podman/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package main

import (
"context"
"errors"
"fmt"
"os"

"github.com/containers/common/pkg/auth"
"github.com/containers/common/pkg/completion"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -48,7 +51,11 @@ func init() {
completion.CompleteCommandFlags(loginCommand, auth.GetLoginFlagsCompletions())

// Podman flags.
flags.BoolVarP(&loginOptions.tlsVerify, "tls-verify", "", false, "Require HTTPS and verify certificates when contacting registries")
secretFlagName := "secret"
flags.BoolVar(&loginOptions.tlsVerify, "tls-verify", false, "Require HTTPS and verify certificates when contacting registries")
flags.String(secretFlagName, "", "Retrieve password from a podman secret")
_ = loginCommand.RegisterFlagCompletionFunc(secretFlagName, common.AutocompleteSecrets)

loginOptions.Stdin = os.Stdin
loginOptions.Stdout = os.Stdout
loginOptions.AcceptUnspecifiedRegistry = true
Expand All @@ -63,6 +70,31 @@ func login(cmd *cobra.Command, args []string) error {
skipTLS = types.NewOptionalBool(!loginOptions.tlsVerify)
}

secretName := cmd.Flag("secret").Value.String()
if len(secretName) > 0 {
if len(loginOptions.Password) > 0 {
return errors.New("--secret can not be used with --password options")
}
if len(loginOptions.Username) == 0 {
loginOptions.Username = secretName
}
var inspectOpts = entities.SecretInspectOptions{
ShowSecret: true,
}
inspected, errs, _ := registry.ContainerEngine().SecretInspect(context.Background(), []string{secretName}, inspectOpts)

if len(errs) > 0 && errs[0] != nil {
return errs[0]
}
if len(inspected) == 0 {
TomSweeneyRedHat marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("no secrets found for %q", secretName)
}
if len(inspected) > 1 {
return fmt.Errorf("unexpected error SecretInspect of a single secret should never return more then one secrets %q", secretName)
}
loginOptions.Password = inspected[0].SecretData
}

sysCtx := &types.SystemContext{
AuthFilePath: loginOptions.AuthFile,
DockerCertPath: loginOptions.CertDir,
Expand Down
14 changes: 13 additions & 1 deletion docs/source/markdown/podman-login.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ Password for registry

Take the password from stdin

#### **--secret**=*name*

Read the password for the registry from the podman secret `name`.
If --username is not specified --username=`name` is used.

@@option tls-verify

#### **--username**, **-u**=*username*
Expand Down Expand Up @@ -79,6 +84,13 @@ Password:
Login Succeeded!
```

```
$ echo -n MySecret! | podman secret create secretname -
a0ad54df3c97cf89d5ca6193c
$ podman login --secret secretname -u testuser quay.io
Login Succeeded!
```

```
$ podman login --tls-verify=false -u test -p test localhost:5000
Login Succeeded!
Expand Down Expand Up @@ -108,7 +120,7 @@ Login Succeeded!
```

## SEE ALSO
**[podman(1)](podman.1.md)**, **[podman-logout(1)](podman-logout.1.md)**, **[containers-auth.json(5)](https://github.com/containers/image/blob/main/docs/containers-auth.json.5.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**, **[containers-registries.conf(5)](https://github.com/containers/image/blob/main/docs/containers-registries.conf.5.md)**
**[podman(1)](podman.1.md)**, **[podman-logout(1)](podman-logout.1.md)**, **[containers-auth.json(5)](https://github.com/containers/image/blob/main/docs/containers-auth.json.5.md)**, **[containers-certs.d(5)](https://github.com/containers/image/blob/main/docs/containers-certs.d.5.md)**, **[containers-registries.conf(5)](https://github.com/containers/image/blob/main/docs/containers-registries.conf.5.md)**, **[podman-secret(1)](podman-secret.1.md)**, **[podman-secret-create(1)](podman-secret-create.1.md)**

## HISTORY
August 2017, Originally compiled by Urvashi Mohnani <[email protected]>
4 changes: 3 additions & 1 deletion docs/source/markdown/podman-secret-create.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ TLS certificates and keys, SSH keys or other important generic strings or binary

Secrets are not committed to an image with `podman commit`, and does not get committed in the archive created by a `podman export` command.

Secrets can also be used to store passwords for `podman login` to authenticate against container registries.

## OPTIONS

#### **--driver**, **-d**=*driver*
Expand Down Expand Up @@ -55,7 +57,7 @@ $ printf <secret> | podman secret create my_secret -
```

## SEE ALSO
**[podman(1)](podman.1.md)**, **[podman-secret(1)](podman-secret.1.md)**
**[podman(1)](podman.1.md)**, **[podman-secret(1)](podman-secret.1.md)**, **[podman-login(1)](podman-login.1.md)**

## HISTORY
January 2021, Originally compiled by Ashley Cui <[email protected]>
43 changes: 43 additions & 0 deletions test/system/150-login.bats
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,49 @@ function _test_skopeo_credential_sharing() {
rm -f $authfile
}

@test "podman login -secret test" {
secret=$(random_string 10)
echo -n ${PODMAN_LOGIN_PASS} > $PODMAN_TMPDIR/secret.file
run_podman secret create $secret $PODMAN_TMPDIR/secret.file
secretID=${output}
run_podman login --tls-verify=false \
--username ${PODMAN_LOGIN_USER} \
--secret ${secretID} \
localhost:${PODMAN_LOGIN_REGISTRY_PORT}
is "$output" "Login Succeeded!" "output from podman login"
# Now log out
run_podman logout localhost:${PODMAN_LOGIN_REGISTRY_PORT}
is "$output" "Removed login credentials for localhost:${PODMAN_LOGIN_REGISTRY_PORT}" \
"output from podman logout"
run_podman secret rm $secret

# test using secret id as --username
run_podman secret create ${PODMAN_LOGIN_USER} $PODMAN_TMPDIR/secret.file
run_podman login --tls-verify=false \
--secret ${PODMAN_LOGIN_USER} \
localhost:${PODMAN_LOGIN_REGISTRY_PORT}
is "$output" "Login Succeeded!" "output from podman login"
# Now log out
run_podman logout localhost:${PODMAN_LOGIN_REGISTRY_PORT}
is "$output" "Removed login credentials for localhost:${PODMAN_LOGIN_REGISTRY_PORT}" \
"output from podman logout"
run_podman secret rm ${PODMAN_LOGIN_USER}

bogus_secret=$(random_string 10)
echo -n ${bogus_secret} > $PODMAN_TMPDIR/secret.file
run_podman secret create $secret $PODMAN_TMPDIR/secret.file
secretID=${output}
run_podman 125 login --tls-verify=false \
--username ${PODMAN_LOGIN_USER} \
--secret ${secretID} \
localhost:${PODMAN_LOGIN_REGISTRY_PORT}

is "$output" "Error: logging into \"localhost:${PODMAN_LOGIN_REGISTRY_PORT}\": invalid username/password" "output from failed podman login"

run_podman secret rm $secret

}

# END cooperation with skopeo
TomSweeneyRedHat marked this conversation as resolved.
Show resolved Hide resolved
# END actual tests
###############################################################################
Expand Down