Skip to content

Commit 0efee60

Browse files
committed
Merge PR oras-project#1006: refactor!: reorganize auth and credential
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
2 parents 0324380 + 342af54 commit 0efee60

38 files changed

+1246
-926
lines changed

docs/tutorial/quickstart.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func main() {
6868
repo.Client = &auth.Client{
6969
Client: retry.DefaultClient,
7070
Cache: auth.NewCache(),
71-
Credential: auth.StaticCredential(repo.Reference.Registry, auth.Credential{
71+
CredentialFunc: credentials.StaticCredentialFunc(repo.Reference.Registry, credentials.Credential{
7272
Username: "username",
7373
Password: "password",
7474
}),
@@ -287,7 +287,7 @@ func main() {
287287
repo.Client = &auth.Client{
288288
Client: retry.DefaultClient,
289289
Cache: auth.NewCache(),
290-
Credential: auth.StaticCredential(repo.Reference.Registry, auth.Credential{
290+
CredentialFunc: credentials.StaticCredentialFunc(repo.Reference.Registry, credentials.Credential{
291291
Username: "username",
292292
Password: "password",
293293
}),

example_copy_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/oras-project/oras-go/v3/internal/spec"
3838
"github.com/oras-project/oras-go/v3/registry/remote"
3939
"github.com/oras-project/oras-go/v3/registry/remote/auth"
40+
"github.com/oras-project/oras-go/v3/registry/remote/credentials"
4041
"github.com/oras-project/oras-go/v3/registry/remote/retry"
4142
)
4243

@@ -451,7 +452,7 @@ func Example_extendedCopyArtifactAndReferrersToRepository() {
451452
repo.Client = &auth.Client{
452453
Client: retry.DefaultClient,
453454
Cache: auth.NewCache(),
454-
Credential: auth.StaticCredential(registry, auth.Credential{
455+
CredentialFunc: credentials.StaticCredentialFunc(registry, credentials.Credential{
455456
Username: "username",
456457
Password: "password",
457458
}),

example_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func Example_pullFilesFromRemoteRepository() {
5050
repo.Client = &auth.Client{
5151
Client: retry.DefaultClient,
5252
Cache: auth.NewCache(),
53-
Credential: auth.StaticCredential(reg, auth.Credential{
53+
CredentialFunc: credentials.StaticCredentialFunc(reg, credentials.Credential{
5454
Username: "username",
5555
Password: "password",
5656
}),
@@ -85,7 +85,7 @@ func Example_pullImageFromRemoteRepository() {
8585
repo.Client = &auth.Client{
8686
Client: retry.DefaultClient,
8787
Cache: auth.NewCache(),
88-
Credential: auth.StaticCredential(reg, auth.Credential{
88+
CredentialFunc: credentials.StaticCredentialFunc(reg, credentials.Credential{
8989
Username: "username",
9090
Password: "password",
9191
}),
@@ -125,9 +125,9 @@ func Example_pullImageUsingDockerCredentials() {
125125
panic(err)
126126
}
127127
repo.Client = &auth.Client{
128-
Client: retry.DefaultClient,
129-
Cache: auth.NewCache(),
130-
Credential: credentials.Credential(credStore), // Use the credentials store
128+
Client: retry.DefaultClient,
129+
Cache: auth.NewCache(),
130+
CredentialFunc: remote.GetCredentialFunc(credStore), // Use the credentials store
131131
}
132132

133133
// 2. Copy from the remote repository to the OCI layout store
@@ -190,7 +190,7 @@ func Example_pushFilesToRemoteRepository() {
190190
repo.Client = &auth.Client{
191191
Client: retry.DefaultClient,
192192
Cache: auth.NewCache(),
193-
Credential: auth.StaticCredential(reg, auth.Credential{
193+
CredentialFunc: credentials.StaticCredentialFunc(reg, credentials.Credential{
194194
Username: "username",
195195
Password: "password",
196196
}),
@@ -218,7 +218,7 @@ func Example_attachBlobToRemoteRepository() {
218218
repo.Client = &auth.Client{
219219
Client: retry.DefaultClient,
220220
Cache: auth.NewCache(),
221-
Credential: auth.StaticCredential(registry, auth.Credential{
221+
CredentialFunc: credentials.StaticCredentialFunc(registry, credentials.Credential{
222222
Username: "username",
223223
Password: "password",
224224
}),
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ See the License for the specific language governing permissions and
1313
limitations under the License.
1414
*/
1515

16-
package credentials
16+
package remote
1717

1818
import (
1919
"context"
2020
"errors"
2121
"fmt"
2222

23-
"github.com/oras-project/oras-go/v3/registry/remote"
2423
"github.com/oras-project/oras-go/v3/registry/remote/auth"
24+
"github.com/oras-project/oras-go/v3/registry/remote/credentials"
2525
)
2626

2727
// ErrClientTypeUnsupported is thrown by Login() when the registry's client type
@@ -32,7 +32,7 @@ var ErrClientTypeUnsupported = errors.New("client type not supported")
3232
// registry's client should be nil or of type *auth.Client. Login uses
3333
// a client local to the function and will not modify the original client of
3434
// the registry.
35-
func Login(ctx context.Context, store Store, reg *remote.Registry, cred auth.Credential) error {
35+
func Login(ctx context.Context, store credentials.Store, reg *Registry, cred credentials.Credential) error {
3636
// create a clone of the original registry for login purpose
3737
regClone := *reg
3838
// we use the original client if applicable, otherwise use a default client
@@ -47,7 +47,7 @@ func Login(ctx context.Context, store Store, reg *remote.Registry, cred auth.Cre
4747
}
4848
regClone.Client = &authClient
4949
// update credentials with the client
50-
authClient.Credential = auth.StaticCredential(reg.Reference.Registry, cred)
50+
authClient.CredentialFunc = credentials.StaticCredentialFunc(reg.Reference.Registry, cred)
5151
// validate and store the credential
5252
if err := regClone.Ping(ctx); err != nil {
5353
return fmt.Errorf("failed to validate the credentials for %s: %w", regClone.Reference.Registry, err)
@@ -60,20 +60,20 @@ func Login(ctx context.Context, store Store, reg *remote.Registry, cred auth.Cre
6060
}
6161

6262
// Logout provides the logout functionality given the registry name.
63-
func Logout(ctx context.Context, store Store, registryName string) error {
63+
func Logout(ctx context.Context, store credentials.Store, registryName string) error {
6464
registryName = ServerAddressFromRegistry(registryName)
6565
if err := store.Delete(ctx, registryName); err != nil {
6666
return fmt.Errorf("failed to delete the credential for %s: %w", registryName, err)
6767
}
6868
return nil
6969
}
7070

71-
// Credential returns a Credential() function that can be used by auth.Client.
72-
func Credential(store Store) auth.CredentialFunc {
73-
return func(ctx context.Context, hostport string) (auth.Credential, error) {
71+
// GetCredentialFunc returns a GetCredentialFunc() function that can be used by auth.Client.
72+
func GetCredentialFunc(store credentials.Store) credentials.CredentialFunc {
73+
return func(ctx context.Context, hostport string) (credentials.Credential, error) {
7474
hostport = ServerAddressFromHostname(hostport)
7575
if hostport == "" {
76-
return auth.EmptyCredential, nil
76+
return credentials.EmptyCredential, nil
7777
}
7878
return store.Get(ctx, hostport)
7979
}

registry/remote/auth/client.go

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"net/url"
2828
"strings"
2929

30+
"github.com/oras-project/oras-go/v3/registry/remote/credentials"
3031
"github.com/oras-project/oras-go/v3/registry/remote/internal/errutil"
3132
"github.com/oras-project/oras-go/v3/registry/remote/retry"
3233
)
@@ -66,29 +67,6 @@ var maxResponseBytes int64 = 128 * 1024 // 128 KiB
6667
// See also ClientID.
6768
var defaultClientID = "oras-go"
6869

69-
// CredentialFunc represents a function that resolves the credential for the
70-
// given registry (i.e. host:port).
71-
//
72-
// [EmptyCredential] is a valid return value and should not be considered as
73-
// an error.
74-
type CredentialFunc func(ctx context.Context, hostport string) (Credential, error)
75-
76-
// StaticCredential specifies static credentials for the given host.
77-
func StaticCredential(registry string, cred Credential) CredentialFunc {
78-
if registry == "docker.io" {
79-
// it is expected that traffic targeting "docker.io" will be redirected
80-
// to "registry-1.docker.io"
81-
// reference: https://github.com/moby/moby/blob/v24.0.0-beta.2/registry/config.go#L25-L48
82-
registry = "registry-1.docker.io"
83-
}
84-
return func(_ context.Context, hostport string) (Credential, error) {
85-
if hostport == registry {
86-
return cred, nil
87-
}
88-
return EmptyCredential, nil
89-
}
90-
}
91-
9270
// Client is an auth-decorated HTTP client.
9371
// Its zero value is a usable client that uses http.DefaultClient with no cache.
9472
type Client struct {
@@ -105,12 +83,12 @@ type Client struct {
10583
// Header contains the custom headers to be added to each request.
10684
Header http.Header
10785

108-
// Credential specifies the function for resolving the credential for the
86+
// CredentialFunc specifies the function for resolving the credential for the
10987
// given registry (i.e. host:port).
11088
// EmptyCredential is a valid return value and should not be considered as
11189
// an error.
11290
// If nil, the credential is always resolved to EmptyCredential.
113-
Credential CredentialFunc
91+
CredentialFunc credentials.CredentialFunc
11492

11593
// Cache caches credentials for direct accessing the remote registry.
11694
// If nil, no cache is used.
@@ -148,11 +126,11 @@ func (c *Client) send(req *http.Request) (*http.Response, error) {
148126
}
149127

150128
// credential resolves the credential for the given registry.
151-
func (c *Client) credential(ctx context.Context, reg string) (Credential, error) {
152-
if c.Credential == nil {
153-
return EmptyCredential, nil
129+
func (c *Client) credential(ctx context.Context, reg string) (credentials.Credential, error) {
130+
if c.CredentialFunc == nil {
131+
return credentials.EmptyCredential, nil
154132
}
155-
return c.Credential(ctx, reg)
133+
return c.CredentialFunc(ctx, reg)
156134
}
157135

158136
// cache resolves the cache.
@@ -291,7 +269,7 @@ func (c *Client) fetchBasicAuth(ctx context.Context, registry string) (string, e
291269
if err != nil {
292270
return "", fmt.Errorf("failed to resolve credential: %w", err)
293271
}
294-
if cred == EmptyCredential {
272+
if cred == credentials.EmptyCredential {
295273
return "", ErrBasicCredentialNotFound
296274
}
297275
if cred.Username == "" || cred.Password == "" {
@@ -310,7 +288,7 @@ func (c *Client) fetchBearerToken(ctx context.Context, registry, realm, service
310288
if cred.AccessToken != "" {
311289
return cred.AccessToken, nil
312290
}
313-
if cred == EmptyCredential || (cred.RefreshToken == "" && !c.ForceAttemptOAuth2) {
291+
if cred == credentials.EmptyCredential || (cred.RefreshToken == "" && !c.ForceAttemptOAuth2) {
314292
return c.fetchDistributionToken(ctx, realm, service, scopes, cred.Username, cred.Password)
315293
}
316294
return c.fetchOAuth2Token(ctx, realm, service, scopes, cred)
@@ -370,7 +348,7 @@ func (c *Client) fetchDistributionToken(ctx context.Context, realm, service stri
370348

371349
// fetchOAuth2Token fetches an OAuth2 access token.
372350
// Reference: https://distribution.github.io/distribution/spec/auth/oauth/
373-
func (c *Client) fetchOAuth2Token(ctx context.Context, realm, service string, scopes []string, cred Credential) (string, error) {
351+
func (c *Client) fetchOAuth2Token(ctx context.Context, realm, service string, scopes []string, cred credentials.Credential) (string, error) {
374352
form := url.Values{}
375353
if cred.RefreshToken != "" {
376354
form.Set("grant_type", "refresh_token")

0 commit comments

Comments
 (0)