Skip to content

Commit

Permalink
commit 3
Browse files Browse the repository at this point in the history
Signed-off-by: jason yang <jasonyangshadow@gmail.com>
  • Loading branch information
JasonYangShadow committed Aug 28, 2024
1 parent 0373b0b commit 34adc9e
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 97 deletions.
18 changes: 2 additions & 16 deletions e2e/internal/e2e/dockerhub_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
package e2e

import (
"encoding/json"
"os"
"path/filepath"
"testing"

"github.com/apptainer/apptainer/internal/pkg/util/ociauth"
"github.com/apptainer/apptainer/internal/pkg/util/user"
"github.com/apptainer/apptainer/pkg/syfs"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/types"
)

const dockerHub = "docker.io"
Expand All @@ -45,19 +43,7 @@ func SetupDockerHubCredentials(t *testing.T) {
func writeDockerHubCredentials(t *testing.T, dir, username, pass string) {
configPath := filepath.Join(dir, ".apptainer", syfs.DockerConfFile)

cf := configfile.ConfigFile{
AuthConfigs: map[string]types.AuthConfig{
dockerHub: {
Username: username,
Password: pass,
},
},
}

configData, err := json.Marshal(cf)
if err != nil {
if err := ociauth.LoginAndStore(dockerHub, username, pass, false, configPath); err != nil {
t.Error(err)
}

os.WriteFile(configPath, configData, 0o600)
}
29 changes: 1 addition & 28 deletions e2e/internal/e2e/home.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"text/template"

"github.com/apptainer/apptainer/internal/pkg/buildcfg"
"github.com/apptainer/apptainer/internal/pkg/util/fs"
"github.com/apptainer/apptainer/internal/pkg/util/user"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -103,23 +102,7 @@ func SetupHomeDirectories(t *testing.T, testRegistry string) {
err = errors.Wrapf(err, "creating temporary home directory at %s", unprivSessionHome)
t.Fatalf("failed to create temporary home: %+v", err)
}
if err := os.Mkdir(filepath.Join(unprivSessionHome, ".apptainer"), 0o700); err != nil {
err = errors.Wrapf(err, "creating temporary .apptainer suvdirectory at %s", unprivSessionHome)
t.Fatalf("failed to create apptainer subdirectory: %+v", err)
}
// No need to check for errors on this - if the file is accessible in the original location, this will work; and if it isn't, it won't.
fs.CopyFile(
filepath.Join(unprivUser.Dir, ".apptainer", "docker-config.json"),
filepath.Join(unprivSessionHome, ".apptainer", "docker-config.json"),
0o600,
)
// Recursive chown
if err := filepath.Walk(unprivSessionHome, func(name string, info os.FileInfo, err error) error {
if err == nil {
err = os.Chown(name, int(unprivUser.UID), int(unprivUser.GID))
}
return err
}); err != nil {
if err := os.Chown(unprivSessionHome, int(unprivUser.UID), int(unprivUser.GID)); err != nil {
err = errors.Wrapf(err, "changing temporary home directory ownership at %s", unprivSessionHome)
t.Fatalf("failed to set temporary home owner: %+v", err)
}
Expand All @@ -128,16 +111,6 @@ func SetupHomeDirectories(t *testing.T, testRegistry string) {
err = errors.Wrapf(err, "changing temporary home directory %s", privSessionHome)
t.Fatalf("failed to create temporary home: %+v", err)
}
if err := os.Mkdir(filepath.Join(privSessionHome, ".apptainer"), 0o700); err != nil {
err = errors.Wrapf(err, "creating temporary .apptainer suvdirectory at %s", privSessionHome)
t.Fatalf("failed to create apptainer subdirectory: %+v", err)
}
// No need to check for errors on this - if the file is accessible in the original location, this will work; and if it isn't, it won't.
fs.CopyFile(
filepath.Join(privUser.Dir, ".apptainer", "docker-config.json"),
filepath.Join(privSessionHome, ".apptainer", "docker-config.json"),
0o600,
)

sourceDir := buildcfg.SOURCEDIR

Expand Down
54 changes: 1 addition & 53 deletions internal/pkg/remote/credential/login_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
package credential

import (
"context"
"crypto/tls"
"fmt"
"net/http"
Expand All @@ -22,10 +21,6 @@ import (
"github.com/apptainer/apptainer/pkg/sylog"

useragent "github.com/apptainer/apptainer/pkg/util/user-agent"
"github.com/docker/cli/cli/config/types"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
)

// loginHandlers contains the registered handlers by scheme.
Expand Down Expand Up @@ -83,63 +78,16 @@ func (h *ociHandler) login(u *url.URL, username, password string, insecure bool,
return nil, err
}

if err := checkOCILogin(registry, username, pass, insecure); err != nil {
if err := ociauth.LoginAndStore(registry, username, pass, insecure, reqAuthFile); err != nil {
return nil, err
}

cf, err := ociauth.ConfigFileFromPath(ociauth.ChooseAuthFile(reqAuthFile))
if err != nil {
return nil, fmt.Errorf("while loading existing OCI registry credentials from %q: %w", ociauth.ChooseAuthFile(reqAuthFile), err)
}

creds := cf.GetCredentialsStore(registry)

// DockerHub requires special logic for historical reasons.
serverAddress := registry
if serverAddress == name.DefaultRegistry {
serverAddress = authn.DefaultAuthKey
}

if err := creds.Store(types.AuthConfig{
Username: username,
Password: pass,
ServerAddress: serverAddress,
}); err != nil {
return nil, fmt.Errorf("while trying to store new credentials: %w", err)
}

sylog.Infof("Token stored in %s", cf.Filename)

return &Config{
URI: u.String(),
Insecure: insecure,
}, nil
}

func checkOCILogin(regName string, username, password string, insecure bool) error {
regOpts := []name.Option{}
if insecure {
regOpts = []name.Option{name.Insecure}
}
reg, err := name.NewRegistry(regName, regOpts...)
if err != nil {
return err
}

auth := authn.FromConfig(authn.AuthConfig{
Username: username,
Password: password,
})

// Creating a new transport pings the registry and works through auth flow.
_, err = transport.NewWithContext(context.TODO(), reg, auth, http.DefaultTransport, nil)
if err != nil {
return err
}

return nil
}

func (h *ociHandler) logout(u *url.URL, reqAuthFile string) error {
if u == nil {
return fmt.Errorf("URL not provided for logout")
Expand Down
63 changes: 63 additions & 0 deletions internal/pkg/util/ociauth/ociauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@
package ociauth

import (
"context"
"fmt"
"net/http"
"os"

"github.com/apptainer/apptainer/internal/pkg/util/fs"
"github.com/apptainer/apptainer/pkg/syfs"
"github.com/apptainer/apptainer/pkg/sylog"
"github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/types"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
)

// ConfigFileFromPath creates a configfile.Configfile object (part of docker/cli
Expand Down Expand Up @@ -47,3 +55,58 @@ func ChooseAuthFile(reqAuthFile string) string {

return syfs.DockerConf()
}

func LoginAndStore(registry, username, password string, insecure bool, reqAuthFile string) error {
if err := checkOCILogin(registry, username, password, insecure); err != nil {
return err
}

cf, err := ConfigFileFromPath(ChooseAuthFile(reqAuthFile))
if err != nil {
return fmt.Errorf("while loading existing OCI registry credentials from %q: %w", ChooseAuthFile(reqAuthFile), err)
}

creds := cf.GetCredentialsStore(registry)

// DockerHub requires special logic for historical reasons.
serverAddress := registry
if serverAddress == name.DefaultRegistry {
serverAddress = authn.DefaultAuthKey
}

if err := creds.Store(types.AuthConfig{
Username: username,
Password: password,
ServerAddress: serverAddress,
}); err != nil {
return fmt.Errorf("while trying to store new credentials: %w", err)
}

sylog.Infof("Token stored in %s", cf.Filename)

return nil
}

func checkOCILogin(regName string, username, password string, insecure bool) error {
regOpts := []name.Option{}
if insecure {
regOpts = []name.Option{name.Insecure}
}
reg, err := name.NewRegistry(regName, regOpts...)
if err != nil {
return err
}

auth := authn.FromConfig(authn.AuthConfig{
Username: username,
Password: password,
})

// Creating a new transport pings the registry and works through auth flow.
_, err = transport.NewWithContext(context.TODO(), reg, auth, http.DefaultTransport, nil)
if err != nil {
return err
}

return nil
}

0 comments on commit 34adc9e

Please sign in to comment.