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

move keyctl to internal & func remove auth from keyring #683

Merged
merged 1 commit into from
Sep 16, 2019
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
9 changes: 9 additions & 0 deletions pkg/keyctl/key.go → internal/pkg/keyctl/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,12 @@ func (k *Key) Unlink() error {
_, err := unix.KeyctlInt(unix.KEYCTL_UNLINK, int(k.id), int(k.ring), 0, 0)
return err
}

// Describe returns a string describing the attributes of a specified key
func (k *Key) Describe() (string, error) {
keyAttr, err := unix.KeyctlString(unix.KEYCTL_DESCRIBE, int(k.id))
if err != nil {
return "", err
}
return keyAttr, nil
}
41 changes: 41 additions & 0 deletions pkg/keyctl/keyring.go → internal/pkg/keyctl/keyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
package keyctl

import (
"unsafe"

"golang.org/x/sys/unix"
)

Expand Down Expand Up @@ -77,3 +79,42 @@ func Link(parent Keyring, child ID) error {
_, err := unix.KeyctlInt(unix.KEYCTL_LINK, int(child.ID()), int(parent.ID()), 0, 0)
return err
}

// ReadUserKeyring reads user keyring and returns slice of key with id(key_serial_t) representing the IDs of all the keys that are linked to it
func ReadUserKeyring() ([]*Key, error) {
var (
b []byte
err error
sizeRead int
)
krSize := 4
size := krSize
b = make([]byte, size)
sizeRead = size + 1
for sizeRead > size {
r1, err := unix.KeyctlBuffer(unix.KEYCTL_READ, unix.KEY_SPEC_USER_KEYRING, b, size)
if err != nil {
return nil, err
}

if sizeRead = int(r1); sizeRead > size {
b = make([]byte, sizeRead)
size = sizeRead
sizeRead = size + 1
} else {
krSize = sizeRead
}
}
keyIDs := getKeyIDsFromByte(b[:krSize])
return keyIDs, err
}

func getKeyIDsFromByte(byteKeyIDs []byte) []*Key {
idSize := 4
var keys []*Key
for idx := 0; idx+idSize <= len(byteKeyIDs); idx = idx + idSize {
tempID := *(*int32)(unsafe.Pointer(&byteKeyIDs[idx]))
keys = append(keys, &Key{id: keyID(tempID)})
}
return keys
}
58 changes: 58 additions & 0 deletions pkg/keyctl/keyring_test.go → internal/pkg/keyctl/keyring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package keyctl

import (
"crypto/rand"
"strings"
"testing"
)

Expand Down Expand Up @@ -143,3 +144,60 @@ func TestUnlink(t *testing.T) {
t.Fatal(err)
}
}

func TestReadKeyring(t *testing.T) {
token := make([]byte, 20)
rand.Read(token)

testname := "testuser"

userKeyring, err := UserKeyring()
if err != nil {
t.Fatal(err)
}

userKey, err := userKeyring.Add(testname, token)
if err != nil {
t.Fatal(err, userKey)
}
keys, err := ReadUserKeyring()
if err != nil {
t.Fatal(err)
}
expectedKeyLen := 1
if len(keys) != 1 {
t.Errorf("expected to read %d userkeyring, but get %d", expectedKeyLen, len(keys))
}
err = Unlink(userKeyring, userKey)
if err != nil {
t.Fatal(err)
}
}

func TestDescribe(t *testing.T) {
token := make([]byte, 20)
rand.Read(token)

testname := "testuser"

userKeyring, err := UserKeyring()
if err != nil {
t.Fatal(err)
}

userKey, err := userKeyring.Add(testname, token)
if err != nil {
t.Fatal(err, userKey)
}
keyAttr, err := userKey.Describe()
if err != nil {
t.Fatal(err)
}
if !strings.Contains(keyAttr, testname) {
t.Errorf("expect description contains %s, but get %s", testname, keyAttr)
}
err = Unlink(userKeyring, userKey)
if err != nil {
t.Fatal(err)
}
}
File renamed without changes.
File renamed without changes.
10 changes: 9 additions & 1 deletion pkg/docker/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,17 @@ func RemoveAuthentication(sys *types.SystemContext, registry string) error {
})
}

// RemoveAllAuthentication deletes all the credentials stored in auth.json
// RemoveAllAuthentication deletes all the credentials stored in auth.json and kernel keyring
func RemoveAllAuthentication(sys *types.SystemContext) error {
return modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) {
if enableKeyring {
err := removeAllAuthFromKernelKeyring()
if err == nil {
logrus.Debugf("removing all credentials from kernel keyring")
return false, nil
}
logrus.Debugf("error removing credentials from kernel keyring")
}
auths.CredHelpers = make(map[string]string)
auths.AuthConfigs = make(map[string]dockerAuthConfig)
return true, nil
Expand Down
40 changes: 38 additions & 2 deletions pkg/docker/config/config_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import (
"fmt"
"strings"

"github.com/containers/image/pkg/keyctl"
"github.com/containers/image/internal/pkg/keyctl"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)

const keyDescribePrefix = "container-registry-login:"

func getAuthFromKernelKeyring(registry string) (string, string, error) {
userkeyring, err := keyctl.UserKeyring()
if err != nil {
Expand Down Expand Up @@ -41,6 +44,39 @@ func deleteAuthFromKernelKeyring(registry string) error {
return key.Unlink()
}

func removeAllAuthFromKernelKeyring() error {
keys, err := keyctl.ReadUserKeyring()
if err != nil {
return err
}

userkeyring, err := keyctl.UserKeyring()
if err != nil {
return err
}

for _, k := range keys {
keyAttr, err := k.Describe()
if err != nil {
return err
}
// split string "type;uid;gid;perm;description"
keyAttrs := strings.SplitN(keyAttr, ";", 5)
if len(keyAttrs) < 5 {
return errors.Errorf("Key attributes of %d are not avaliable", k.ID())
}
keyDescribe := keyAttrs[4]
if strings.HasPrefix(keyDescribe, keyDescribePrefix) {
err := keyctl.Unlink(userkeyring, k)
if err != nil {
return errors.Wrapf(err, "error unlinking key %d", k.ID())
}
logrus.Debugf("unlinked key %d:%s", k.ID(), keyAttr)
}
}
return nil
}

func setAuthToKernelKeyring(registry, username, password string) error {
keyring, err := keyctl.SessionKeyring()
if err != nil {
Expand Down Expand Up @@ -75,5 +111,5 @@ func setAuthToKernelKeyring(registry, username, password string) error {
}

func genDescription(registry string) string {
return fmt.Sprintf("container-registry-login:%s", registry)
return fmt.Sprintf("%s%s", keyDescribePrefix, registry)
}
4 changes: 4 additions & 0 deletions pkg/docker/config/config_unsupported.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ func deleteAuthFromKernelKeyring(registry string) error {
func setAuthToKernelKeyring(registry, username, password string) error {
return ErrNotSupported
}

func removeAllAuthFromKernelKeyring() error {
return ErrNotSupported
Copy link
Collaborator

Choose a reason for hiding this comment

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

(Non-blocking: This will cause pointless debug logs about failures on non-Linux platforms. OTOH it is consistent with the others, so it would be better to clean this up in a separate PR.)

}