Skip to content

Commit ae4a6cf

Browse files
committed
Allow ECR registries by default
1 parent f68ad77 commit ae4a6cf

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

components/image-builder-mk3/pkg/auth/auth.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"encoding/base64"
1212
"fmt"
1313
"os"
14+
"regexp"
1415
"strings"
1516
"sync"
1617
"time"
@@ -141,16 +142,21 @@ type ECRAuthenticator struct {
141142
ecrAuthLock sync.Mutex
142143
}
143144

145+
const (
146+
// ECR tokens are valid for 12h [1], and we want to ensure we refresh at least twice a day before full expiry.
147+
//
148+
// [1] https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_GetAuthorizationToken.html
149+
ecrTokenRefreshTime = 4 * time.Hour
150+
)
151+
144152
func (ath *ECRAuthenticator) Authenticate(ctx context.Context, registry string) (auth *Authentication, err error) {
145-
// TODO(cw): find better way to detect if ref is an ECR repo
146-
if !strings.Contains(registry, ".dkr.") || !strings.Contains(registry, ".amazonaws.com") {
153+
if !isECRRegistry(registry) {
147154
return nil, nil
148155
}
149156

150157
ath.ecrAuthLock.Lock()
151158
defer ath.ecrAuthLock.Unlock()
152-
// ECR tokens are valid for 12h: https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_GetAuthorizationToken.html
153-
if time.Since(ath.ecrAuthLastRefreshTime) > 10*time.Hour {
159+
if time.Since(ath.ecrAuthLastRefreshTime) > ecrTokenRefreshTime {
154160
tknout, err := ath.ecrc.GetAuthorizationToken(ctx, &ecr.GetAuthorizationTokenInput{})
155161
if err != nil {
156162
return nil, err
@@ -193,6 +199,13 @@ func (a *Authentication) Empty() bool {
193199
return false
194200
}
195201

202+
var ecrRegistryRegexp = regexp.MustCompile(`\d{12}.dkr.ecr.\w+-\w+-\w+.amazonaws.com`)
203+
204+
// isECRRegistry returns true if the registry domain is an ECR registry
205+
func isECRRegistry(domain string) bool {
206+
return ecrRegistryRegexp.MatchString(domain)
207+
}
208+
196209
// AllowedAuthFor describes for which repositories authentication may be provided for
197210
type AllowedAuthFor struct {
198211
All bool
@@ -293,7 +306,7 @@ func (a AllowedAuthFor) GetAuthFor(ctx context.Context, auth RegistryAuthenticat
293306
// If we haven't found authentication using the built-in way, we'll resort to additional auth
294307
// the user sent us.
295308
defer func() {
296-
if err != nil || (res != nil && (res.Auth != "" || res.Password != "")) {
309+
if err != nil || !res.Empty() {
297310
return
298311
}
299312

@@ -306,10 +319,15 @@ func (a AllowedAuthFor) GetAuthFor(ctx context.Context, auth RegistryAuthenticat
306319
}()
307320

308321
var regAllowed bool
309-
if a.IsAllowAll() {
322+
switch {
323+
case a.IsAllowAll():
310324
// free for all
311325
regAllowed = true
312-
} else {
326+
case isECRRegistry(reg):
327+
// We allow ECR registries by default to support private ECR registries OOTB.
328+
// The AWS IAM permissions dictate what users actually have access to.
329+
regAllowed = true
330+
default:
313331
for _, a := range a.Explicit {
314332
if a == reg {
315333
regAllowed = true
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License.AGPL.txt in the project root for license information.
4+
5+
package auth
6+
7+
import (
8+
"testing"
9+
10+
"github.com/google/go-cmp/cmp"
11+
)
12+
13+
func TestIsECRRegistry(t *testing.T) {
14+
tests := []struct {
15+
Registry string
16+
Expectation bool
17+
}{
18+
{Registry: "422899872803.dkr.ecr.eu-central-1.amazonaws.com/private-repo-demo:latest", Expectation: true},
19+
{Registry: "422899872803.dkr.ecr.eu-central-1.amazonaws.com", Expectation: true},
20+
{Registry: "index.docker.io/foo:bar", Expectation: false},
21+
}
22+
23+
for _, test := range tests {
24+
t.Run(test.Registry, func(t *testing.T) {
25+
act := isECRRegistry(test.Registry)
26+
27+
if diff := cmp.Diff(test.Expectation, act); diff != "" {
28+
t.Errorf("isECRRegistry() mismatch (-want +got):\n%s", diff)
29+
}
30+
})
31+
}
32+
}

0 commit comments

Comments
 (0)