Skip to content

Commit

Permalink
cleanup(registry/auth) refactor OCI registry authentication and crede…
Browse files Browse the repository at this point in the history
…ntial storage

Consoldidate all authentication methods in a single client and only
use credential stores as source of truth. falcoctl config can still
be used for logging into registries.

Signed-off-by: Maximilian Frank <[email protected]>
  • Loading branch information
max-frank authored and poiana committed Jun 21, 2023
1 parent cc49e6c commit 4105621
Show file tree
Hide file tree
Showing 27 changed files with 649 additions and 594 deletions.
23 changes: 0 additions & 23 deletions cmd/artifact/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/falcosecurity/falcoctl/cmd/artifact/list"
"github.com/falcosecurity/falcoctl/cmd/artifact/search"
"github.com/falcosecurity/falcoctl/internal/config"
"github.com/falcosecurity/falcoctl/internal/login"
"github.com/falcosecurity/falcoctl/pkg/index/cache"
commonoptions "github.com/falcosecurity/falcoctl/pkg/options"
)
Expand All @@ -42,8 +41,6 @@ func NewArtifactCmd(ctx context.Context, opt *commonoptions.CommonOptions) *cobr
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
var indexes []config.Index
var indexCache *cache.Cache
var basicAuths []config.BasicAuth
var oauthAuths []config.OauthAuth
var err error

opt.Initialize()
Expand All @@ -64,26 +61,6 @@ func NewArtifactCmd(ctx context.Context, opt *commonoptions.CommonOptions) *cobr
// Save the index cache for later use by the sub commands.
opt.Initialize(commonoptions.WithIndexCache(indexCache))

// Authenticate for commands that requires it.
if cmd.CalledAs() != list.CommandName && cmd.CalledAs() != search.CommandName {
// Perform authentication using basic auth.
if basicAuths, err = config.BasicAuths(); err != nil {
return err
}
if err = login.PerformBasicAuthsLogin(ctx, basicAuths); err != nil {
return err
}

// Perform authentications using oauth auth.
if oauthAuths, err = config.OauthAuths(); err != nil {
return err
}

if err = login.PerformOauthAuths(ctx, opt, oauthAuths); err != nil {
return err
}
}

return nil
},
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/artifact/follow/follow.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ func (o *artifactFollowOptions) RunArtifactFollow(ctx context.Context, args []st
FalcoVersions: o.versions,
AllowedTypes: o.allowedTypes,
}
fol, err := follower.New(ctx, ref, o.Printer, cfg)
fol, err := follower.New(ref, o.Printer, cfg)
if err != nil {
return fmt.Errorf("unable to create the follower for ref %q: %w", ref, err)
}
Expand Down
19 changes: 8 additions & 11 deletions cmd/artifact/info/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (
"github.com/spf13/cobra"
"oras.land/oras-go/v2/registry"

"github.com/falcosecurity/falcoctl/internal/utils"
"github.com/falcosecurity/falcoctl/pkg/oci/repository"
ociutils "github.com/falcosecurity/falcoctl/pkg/oci/utils"
"github.com/falcosecurity/falcoctl/pkg/options"
"github.com/falcosecurity/falcoctl/pkg/output"
)
Expand Down Expand Up @@ -60,6 +60,13 @@ func NewArtifactInfoCmd(ctx context.Context, opt *options.CommonOptions) *cobra.

func (o *artifactInfoOptions) RunArtifactInfo(ctx context.Context, args []string) error {
var data [][]string

client, err := ociutils.Client()
if err != nil {
return err
}

// resolve references
for _, name := range args {
var ref string
parsedRef, err := registry.ParseReference(name)
Expand All @@ -75,16 +82,6 @@ func (o *artifactInfoOptions) RunArtifactInfo(ctx context.Context, args []string
ref = parsedRef.String()
}

reg, err := utils.GetRegistryFromRef(ref)
if err != nil {
return err
}

client, err := utils.ClientForRegistry(ctx, reg, o.PlainHTTP, o.Printer)
if err != nil {
return err
}

repo, err := repository.NewRepository(ref,
repository.WithClient(client),
repository.WithPlainHTTP(o.PlainHTTP))
Expand Down
28 changes: 7 additions & 21 deletions cmd/artifact/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/falcosecurity/falcoctl/internal/config"
"github.com/falcosecurity/falcoctl/internal/utils"
"github.com/falcosecurity/falcoctl/pkg/oci"
ociutils "github.com/falcosecurity/falcoctl/pkg/oci/utils"
"github.com/falcosecurity/falcoctl/pkg/options"
)

Expand Down Expand Up @@ -185,23 +186,19 @@ func (o *artifactInstallOptions) RunArtifactInstall(ctx context.Context, args []
}
defer os.RemoveAll(tmpDir)

// Create registry puller with auto login enabled
puller, err := ociutils.Puller(o.PlainHTTP, o.Printer)
if err != nil {
return err
}

// Specify how to pull config layer for each artifact requested by user.
resolver := artifactConfigResolver(func(ref string) (*oci.RegistryResult, error) {
ref, err := o.IndexCache.ResolveReference(ref)
if err != nil {
return nil, err
}

reg, err := utils.GetRegistryFromRef(ref)
if err != nil {
return nil, err
}

puller, err := utils.PullerForRegistry(ctx, reg, o.PlainHTTP, o.Printer)
if err != nil {
return nil, err
}

artifactConfig, err := puller.PullConfigLayer(ctx, ref)
if err != nil {
return nil, err
Expand Down Expand Up @@ -234,7 +231,6 @@ func (o *artifactInstallOptions) RunArtifactInstall(ctx context.Context, args []

o.Printer.Info.Printfln("Installing the following artifacts: %v", refs)

// Install artifacts
for _, ref := range refs {
ref, err = o.IndexCache.ResolveReference(ref)
if err != nil {
Expand All @@ -243,16 +239,6 @@ func (o *artifactInstallOptions) RunArtifactInstall(ctx context.Context, args []

o.Printer.Info.Printfln("Preparing to pull %q", ref)

reg, err := utils.GetRegistryFromRef(ref)
if err != nil {
return err
}

puller, err := utils.PullerForRegistry(ctx, reg, o.PlainHTTP, o.Printer)
if err != nil {
return err
}

if err := puller.CheckAllowedType(ctx, ref, o.allowedTypes.Types); err != nil {
return err
}
Expand Down
3 changes: 1 addition & 2 deletions cmd/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,7 @@ var registryPushTests = Describe("push", func() {
args = []string{registryCmd, pushCmd, "noregistry/testrules", "--config", configFile, rulesfiletgz,
"--type", "rulesfile", "--version", "1.1.1", "--plain-http"}
})
pushAssertFailedBehavior(registryPushUsage, "ERRO: an error occurred while creating the pusher for registry "+
"noregistry: unable to connect to remote "+
pushAssertFailedBehavior(registryPushUsage, "ERRO: unable to connect to remote "+
"registry \"noregistry\": Get \"http://noregistry/v2/\": dial tcp: lookup noregistry")
})

Expand Down
59 changes: 11 additions & 48 deletions cmd/registry/auth/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ import (
"context"
"fmt"

credentials "github.com/oras-project/oras-credentials-go"
"github.com/spf13/cobra"
"oras.land/oras-go/v2/registry/remote/auth"

"github.com/falcosecurity/falcoctl/internal/config"
"github.com/falcosecurity/falcoctl/internal/login/basic"
"github.com/falcosecurity/falcoctl/internal/utils"
"github.com/falcosecurity/falcoctl/pkg/oci/authn"
"github.com/falcosecurity/falcoctl/pkg/oci/registry"
"github.com/falcosecurity/falcoctl/pkg/options"
)

Expand Down Expand Up @@ -63,59 +63,22 @@ func (o *loginOptions) RunBasic(ctx context.Context, args []string) error {
return err
}

cred := &auth.Credential{
Username: user,
Password: token,
}

if err = DoLogin(ctx, reg, cred); err != nil {
return err
}
// create empty client
client := authn.NewClient()

currentAuths, err := config.BasicAuths()
if err != nil {
return fmt.Errorf("unable to get basicAuths from viper: %w", err)
}

for _, a := range currentAuths {
if a.Registry == reg {
o.Printer.Verbosef("credentials for registry %q already exists in the config file %q", reg, config.ConfigPath)
return nil
}
}

currentAuths = append(currentAuths, config.BasicAuth{
Registry: reg,
User: user,
Password: token,
// create credential store
credentialStore, err := credentials.NewStore(config.RegistryCredentialConfPath(), credentials.StoreOptions{
AllowPlaintextPut: true,
})

if err := config.UpdateConfigFile(config.RegistryAuthBasicKey, currentAuths, o.ConfigFile); err != nil {
return fmt.Errorf("unable to update basic auths credential list in the config file %q: %w", config.ConfigPath, err)
}
o.Printer.Verbosef("credentials added to config file %q", config.ConfigPath)

o.Printer.Success.Println("Login succeeded")
return nil
}

// DoLogin checks if passed credentials are correct and stores them.
func DoLogin(ctx context.Context, reg string, cred *auth.Credential) error {
client := authn.NewClient(authn.WithCredentials(cred))
r, err := registry.NewRegistry(reg, registry.WithClient(client))
if err != nil {
return err
}

if err := r.CheckConnection(ctx); err != nil {
return fmt.Errorf("unable to connect to registry %q: %w", reg, err)
return fmt.Errorf("unable to create new store: %w", err)
}

// Store validated credentials
err = authn.Login(reg, cred.Username, cred.Password)
if err != nil {
if err := basic.Login(ctx, client, credentialStore, reg, user, token); err != nil {
return err
}
o.Printer.Verbosef("credentials added to credential store")
o.Printer.Success.Println("Login succeeded")

return nil
}
47 changes: 6 additions & 41 deletions cmd/registry/auth/oauth/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ package oauth

import (
"context"
"fmt"

"github.com/spf13/cobra"
"golang.org/x/oauth2/clientcredentials"

"github.com/falcosecurity/falcoctl/internal/config"
"github.com/falcosecurity/falcoctl/internal/utils"
"github.com/falcosecurity/falcoctl/internal/login/oauth"
"github.com/falcosecurity/falcoctl/pkg/options"
)

Expand Down Expand Up @@ -61,7 +60,7 @@ func NewOauthCmd(ctx context.Context, opt *options.CommonOptions) *cobra.Command
SilenceErrors: true,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
return o.RunOauth(ctx, args)
return o.RunOAuth(ctx, args)
},
}

Expand All @@ -85,46 +84,12 @@ func NewOauthCmd(ctx context.Context, opt *options.CommonOptions) *cobra.Command
return cmd
}

// RunOauth implements the registry oauth command.
func (o *RegistryOauthOptions) RunOauth(ctx context.Context, args []string) error {
// RunOAuth executes the business logic for the oauth command.
func (o *RegistryOauthOptions) RunOAuth(ctx context.Context, args []string) error {
reg := args[0]

// Check that we can retrieve token using the passed credentials.
_, err := o.Conf.Token(ctx)
if err != nil {
return fmt.Errorf("wrong client credentials, unable to retrieve token: %w", err)
}

// Save client credentials to file.
if err = utils.WriteClientCredentials(reg, &o.Conf); err != nil {
return fmt.Errorf("unable to save token: %w", err)
}

currentAuths, err := config.OauthAuths()
if err != nil {
return fmt.Errorf("unable to get oauthAuths from viper: %w", err)
}

for _, a := range currentAuths {
if a.Registry == reg {
o.Printer.Verbosef("credentials for registry %q already exists in the config file %q", reg, config.ConfigPath)
return nil
}
}

currentAuths = append(currentAuths, config.OauthAuth{
Registry: reg,
ClientSecret: o.Conf.ClientSecret,
ClientID: o.Conf.ClientID,
TokenURL: o.Conf.TokenURL,
})

if err := config.UpdateConfigFile(config.RegistryAuthOauthKey, currentAuths, o.ConfigFile); err != nil {
return fmt.Errorf("unable to update oauth auths credential list in the config file %q: %w", config.ConfigPath, err)
if err := oauth.Login(ctx, reg, &o.Conf); err != nil {
return err
}
o.Printer.Verbosef("credentials added to config file %q", config.ConfigPath)

o.Printer.Success.Printfln("client credentials correctly saved in %q", config.ClientCredentialsFile)

return nil
}
32 changes: 13 additions & 19 deletions cmd/registry/pull/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ import (

"github.com/spf13/cobra"

"github.com/falcosecurity/falcoctl/internal/config"
"github.com/falcosecurity/falcoctl/internal/login"
"github.com/falcosecurity/falcoctl/internal/utils"
ociutils "github.com/falcosecurity/falcoctl/pkg/oci/utils"
"github.com/falcosecurity/falcoctl/pkg/options"
"github.com/falcosecurity/falcoctl/pkg/output"
)
Expand Down Expand Up @@ -82,28 +81,17 @@ func NewPullCmd(ctx context.Context, opt *options.CommonOptions) *cobra.Command
SilenceErrors: true,
SilenceUsage: true,
PreRunE: func(cmd *cobra.Command, args []string) error {
var basicAuths []config.BasicAuth
var oauthAuths []config.OauthAuth
var err error

if err := o.Validate(); err != nil {
return err
}

// Perform authentications using basic auth.
if basicAuths, err = config.BasicAuths(); err != nil {
return err
}
if err = login.PerformBasicAuthsLogin(ctx, basicAuths); err != nil {
return err
}
ref := args[0]

// Perform authentications using oauth auth.
if oauthAuths, err = config.OauthAuths(); err != nil {
_, err := utils.GetRegistryFromRef(ref)
if err != nil {
return err
}

return login.PerformOauthAuths(ctx, o.CommonOptions, oauthAuths)
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return o.RunPull(ctx, args)
Expand All @@ -119,18 +107,24 @@ func NewPullCmd(ctx context.Context, opt *options.CommonOptions) *cobra.Command
// RunPull executes the business logic for the pull command.
func (o *pullOptions) RunPull(ctx context.Context, args []string) error {
ref := args[0]
o.Printer.Info.Printfln("Preparing to pull artifact %q", args[0])

registry, err := utils.GetRegistryFromRef(ref)
if err != nil {
return err
}

puller, err := utils.PullerForRegistry(ctx, registry, o.PlainHTTP, o.Printer)
puller, err := ociutils.Puller(o.PlainHTTP, o.Printer)
if err != nil {
return fmt.Errorf("an error occurred while creating the puller for registry %s: %w", registry, err)
}

err = ociutils.CheckConnectionForRegistry(ctx, puller.Client, o.PlainHTTP, registry)
if err != nil {
return err
}

o.Printer.Info.Printfln("Preparing to pull artifact %q", args[0])

if o.destDir == "" {
o.Printer.Info.Printfln("Pulling artifact in the current directory")
} else {
Expand Down
Loading

0 comments on commit 4105621

Please sign in to comment.