Skip to content

Commit

Permalink
⚙️ Expose auth options for registry image resolver, load ACR token la…
Browse files Browse the repository at this point in the history
…zily.

Signed-off-by: Preslav <[email protected]>
  • Loading branch information
preslavgerchev committed Apr 9, 2024
1 parent 6be5466 commit 11dede7
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 42 deletions.
21 changes: 12 additions & 9 deletions providers/os/connection/container/acr/acr_auth_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,23 @@ const (
// implemented according to https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md
type acrAuthHelper struct {
httpClient *http.Client
aadToken azcore.TokenCredential
tokenFn func() (azcore.TokenCredential, error)
cache map[string]string
}

func newAcrAuthHelperFromToken(token azcore.TokenCredential) *acrAuthHelper {
func NewAcrAuthHelperFromToken(tokenFn func() (azcore.TokenCredential, error)) *acrAuthHelper {
return &acrAuthHelper{
httpClient: http.DefaultClient,
aadToken: token,
tokenFn: tokenFn,
cache: make(map[string]string),
}
}

func NewAcrAuthHelper() (*acrAuthHelper, error) {
token, err := azauth.GetChainedToken(nil)
if err != nil {
return nil, err
func NewAcrAuthHelper() *acrAuthHelper {
fn := func() (azcore.TokenCredential, error) {
return azauth.GetChainedToken(nil)
}
return newAcrAuthHelperFromToken(token), nil
return NewAcrAuthHelperFromToken(fn)
}

func (a *acrAuthHelper) getRefreshUrl(serverUrl string) string {
Expand All @@ -58,7 +57,11 @@ func (a *acrAuthHelper) getRefreshToken(ctx context.Context, serverUrl string) (
log.Debug().Str("server", serverUrl).Msg("using cached acr refresh token")
return refreshToken, nil
}
rawAadToken, err := a.aadToken.GetToken(ctx, policy.TokenRequestOptions{
t, err := a.tokenFn()
if err != nil {
return "", err
}
rawAadToken, err := t.GetToken(ctx, policy.TokenRequestOptions{
Scopes: []string{msScope},
})
if err != nil {
Expand Down
8 changes: 1 addition & 7 deletions providers/os/connection/container/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (

"github.com/awslabs/amazon-ecr-credential-helper/ecr-login"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/rs/zerolog/log"
"go.mondoo.com/cnquery/v10/providers/os/connection/container/acr"
)

Expand All @@ -25,12 +24,7 @@ func getKeychains(name string) []authn.Keychain {
kcs = append(kcs, authn.NewKeychainFromHelper(ecr.NewECRHelper()))
}
if strings.Contains(name, acrIndicator) {
acr, err := acr.NewAcrAuthHelper()
if err == nil {
kcs = append(kcs, authn.NewKeychainFromHelper(acr))
} else {
log.Debug().Err(err).Msg("failed to create ACR auth helper")
}
kcs = append(kcs, authn.NewKeychainFromHelper(acr.NewAcrAuthHelper()))
}
return kcs
}
Expand Down
1 change: 1 addition & 0 deletions providers/os/connection/container/image_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func NewImageConnection(id uint32, conf *inventory.Config, asset *inventory.Asse

return tar.NewConnection(id, conf, asset,
tar.WithFetchFn(func() (string, error) {
log.Debug().Msg("tar> starting image extract to temporary file")
err = tar.StreamToTmpFile(mutate.Extract(img), f)
if err != nil {
_ = os.Remove(f.Name())
Expand Down
2 changes: 1 addition & 1 deletion providers/os/connection/tar/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func RandomFile() (*os.File, error) {
}

// StreamToTmpFile streams a binary stream into a file. The user of this method
// is responsible for deleting the file late
// is responsible for deleting the file later
func StreamToTmpFile(r io.ReadCloser, outFile *os.File) error {
defer outFile.Close()
_, err := io.Copy(outFile, r)
Expand Down
66 changes: 42 additions & 24 deletions providers/os/resources/discovery/container_registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,48 +23,66 @@ import (
"go.mondoo.com/cnquery/v10/providers/os/id/containerid"
)

func NewContainerRegistryResolver() *DockerRegistryImages {
return &DockerRegistryImages{}
func NewContainerRegistryResolver(opts ...remote.Option) *DockerRegistryImages {
return &DockerRegistryImages{
opts: opts,
}
}

type DockerRegistryImages struct {
opts []remote.Option
Insecure bool
DisableKeychainAuth bool
}

func (a *DockerRegistryImages) remoteOptions(name string) []remote.Option {
options := []remote.Option{}
func (a *DockerRegistryImages) DefaultAuth(name string) remote.Option {
kcs := auth.ConstructKeychain(name)
return remote.WithAuthFromKeychain(kcs)
}

func (a *DockerRegistryImages) InsecureTransportOpt() remote.Option {
// NOTE: config to get remote running with an insecure registry, we need to override the TLSClientConfig
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
return remote.WithTransport(tr)
}

func (a *DockerRegistryImages) DefaultOpts(name string) []remote.Option {
options := []remote.Option{}
// does not work with bearer auth, therefore it need to be disabled when other remote auth options are used
// TODO: we should implement this a bit differently
if !a.DisableKeychainAuth {
kcs := auth.ConstructKeychain(name)
options = append(options, remote.WithAuthFromKeychain(kcs))
options = append(options, a.DefaultAuth(name))
}
if a.Insecure {
// NOTE: config to get remote running with an insecure registry, we need to override the TLSClientConfig
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
options = append(options, remote.WithTransport(tr))
options = append(options, a.InsecureTransportOpt())
}

return options
}

func (a *DockerRegistryImages) remoteOptions(name string) []remote.Option {
// either use the provided options or the default options
if len(a.opts) > 0 {
return a.opts
}
return a.DefaultOpts(name)
}

func (a *DockerRegistryImages) Repositories(reg name.Registry) ([]string, error) {
n := 100
last := ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ func (r *Resolver) AvailableDiscoveryTargets() []string {
return []string{"auto", "all"}
}

// func (r *Resolver) Resolve(ctx context.Context, root *inventory.Asset, conf *inventory.Config, credsResolver vault.Resolver, sfn common.QuerySecretFn, userIdDetectors ...providers.PlatformIdDetector) ([]*inventory.Asset, error) {
func (r *Resolver) Resolve(ctx context.Context, root *inventory.Asset, conf *inventory.Config, credsResolver vault.Resolver) ([]*inventory.Asset, error) {
resolved := []*inventory.Asset{}

Expand Down

0 comments on commit 11dede7

Please sign in to comment.