Skip to content

Commit c092e6f

Browse files
loresusoalacuku
authored andcommitted
new: implement the push command
Signed-off-by: Lorenzo Susini <[email protected]> Co-authored-by: Aldo Lacuku <[email protected]>
1 parent 8bca6f5 commit c092e6f

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

cmd/push.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Copyright 2022 The Falco Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package cmd
16+
17+
import (
18+
"context"
19+
"fmt"
20+
"regexp"
21+
"strings"
22+
23+
"github.com/spf13/cobra"
24+
25+
"github.com/falcosecurity/falcoctl/pkg/oci"
26+
"github.com/falcosecurity/falcoctl/pkg/oci/authn"
27+
ocipusher "github.com/falcosecurity/falcoctl/pkg/oci/pusher"
28+
commonoptions "github.com/falcosecurity/falcoctl/pkg/options"
29+
)
30+
31+
type pushOptions struct {
32+
*commonoptions.CommonOptions
33+
artifactType oci.ArtifactType
34+
dependencies []string
35+
}
36+
37+
func (o *pushOptions) Validate() error {
38+
r := regexp.MustCompile(`^[a-z]+:\d+.\d+.\d+`)
39+
40+
for _, dep := range o.dependencies {
41+
if ok := r.MatchString(dep); !ok {
42+
return fmt.Errorf("wrong dependency format: %s", dep)
43+
}
44+
}
45+
46+
return nil
47+
}
48+
49+
// NewPushCmd returns the push command.
50+
func NewPushCmd(opt *commonoptions.CommonOptions) *cobra.Command {
51+
o := pushOptions{
52+
CommonOptions: opt,
53+
}
54+
55+
cmd := &cobra.Command{
56+
Use: "push filename hostname/repo:tag",
57+
DisableFlagsInUseLine: true,
58+
Short: "Push a Falco OCI artifact to a registry",
59+
Long: "Push Falco rules or plugins OCI artifacts to a registry",
60+
Args: cobra.ExactArgs(2),
61+
PreRun: func(cmd *cobra.Command, args []string) {
62+
o.Printer.CheckErr(o.Validate())
63+
},
64+
Run: func(cmd *cobra.Command, args []string) {
65+
o.Printer.CheckErr(o.RunPush(args))
66+
},
67+
}
68+
69+
cmd.Flags().VarP(&o.artifactType, "type", "t", `type of artifact to be pushed. Allowed values: "rule", "plugin"`)
70+
err := cmd.MarkFlagRequired("type")
71+
if err != nil {
72+
o.Printer.Error.Println("cannot mark type flag as required")
73+
}
74+
cmd.Flags().StringArrayVarP(&o.dependencies, "dependency", "d", []string{},
75+
"define a rule to plugin dependency. Example: '--dependency cloudtrail:1.2.3")
76+
77+
return cmd
78+
}
79+
80+
// RunPush executes the business logic for the push command.
81+
func (o *pushOptions) RunPush(args []string) error {
82+
ctx := context.TODO()
83+
path := args[0]
84+
ref := args[1]
85+
index := strings.Index(ref, "/")
86+
if index <= 0 {
87+
return fmt.Errorf("cannot extract registry name")
88+
}
89+
90+
registry := ref[0:index]
91+
92+
credentialStore, err := authn.NewStore([]string{}...)
93+
if err != nil {
94+
return err
95+
}
96+
cred, err := credentialStore.Credential(ctx, registry)
97+
if err != nil {
98+
return err
99+
}
100+
client := authn.NewClient(cred)
101+
102+
pusher, err := ocipusher.NewPusher(ctx, client)
103+
if err != nil {
104+
o.Printer.Error.Println(err.Error())
105+
return err
106+
}
107+
108+
res, err := pusher.Push(ctx, o.artifactType, path, ref, o.dependencies...)
109+
if err != nil {
110+
o.Printer.Error.Println(err.Error())
111+
return err
112+
}
113+
114+
o.Printer.DefaultText.Printf("Artifact pushed. Digest: %s\n", res.Digest)
115+
116+
return nil
117+
}

0 commit comments

Comments
 (0)