Skip to content

Commit

Permalink
Fix bugs in v0.1.0 (#60)
Browse files Browse the repository at this point in the history
* Update auth through GetCreds() in Pull and Push commands

Signed-off-by: Santosh Kaluskar <ksantosh@intelops.dev>

* Update cuemod init also to accept oci URLs in --tools flag

Signed-off-by: Santosh Kaluskar <ksantosh@intelops.dev>

* Add UserAgent for HTTP requests made while calling OCI registries and fetch version info based git tag

Signed-off-by: Santosh Kaluskar <ksantosh@intelops.dev>

* Update README for cuemod init command

Signed-off-by: Santosh Kaluskar <ksantosh@intelops.dev>

* Add artifact signing with cosign key as well

Signed-off-by: Santosh Kaluskar <ksantosh@intelops.dev>

* Rebase on main and fix typos

Signed-off-by: Santosh Kaluskar <ksantosh@intelops.dev>

---------

Signed-off-by: Santosh Kaluskar <ksantosh@intelops.dev>
  • Loading branch information
santoshkal authored Apr 12, 2024
1 parent 10baf50 commit 5f6411c
Show file tree
Hide file tree
Showing 15 changed files with 204 additions and 138 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ input_dockerfile.json
Dockerfile*
genval
cosign
.idea
.todo

18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,21 @@ Genval streamlines the creation of such a workspace for several technologies, in
To initiate a workspace, utilize the `cuemod init` command and specify the desired technology using the `--tool` flag
The `cuemod init` command acts as a helper command, facilitating the creation of all necessary files for working in the *cue mode*. It validates and retrieves all required files from the OCI registry, placing them on disk for use with the cue command.
The `cuemod init` command acts as a helper command, facilitating the creation of all necessary files for working with the `cue` command. It validates and retrieves all required dir/files from the OCI registry, placing them on disk for use with the `cue` command.
Currently, the supported tools for initializing `cuemods` are `k8s`, `tektoncd`, `argocd`. `crossplane`, and `clusterAPI`.
```shell
$ genval cuemod init --tool=k8s`
$ genval cuemod init --tool=k8s
```
This command will create a new directory in users current working directory with name `cuemod-k8s:1.29` with following structure:
> Note: If a workspace for a tool that is not available in the above list of supported tools. Genval also supports pulling a custom workspace built and stored by users in OCI registries. The only requirement while building and pushing the workspace to OCI registry, is the the directory structure, which should exactly be in the following order:
```shell
.
├── cue.mod # This directory may contain all Kubernetes types in cue format, generated with "cue get go k8s.io/apis/..." cue command.
└── policy.cue # This is a .cue file containing the Cue definitions/policies
```
`genval cuemod init --tool k8s` command will create a new directory in users current working directory with name `cuemod-k8s:1.29` with following structure:
```shell
./k8s:1.29/
Expand Down Expand Up @@ -323,8 +331,8 @@ Genval offers comprehensive management capabilities for the configuration files
To bolster supply chain security workflows, Genval enables users to sign the artifacts after storing them in the registry. Similarly, when pulling any artifact, Genval provides functionality to verify the signatures of the artifacts. This feature leverages **Sigstore's Cosign keyless mode** of signing and verifying artifacts. However, users can also utilize their own private and public keys for signing and verifying the artifacts respectively.

To facilitate authentication with container registries, Genval initially searches for the `./docker/config.json` file in the user's
`$HOME` directory. If this file is found, Genval utilizes it for authentication. However, if the file is not present,
To facilitate authentication with container registries, Genval initially looks for the `~/.docker/config.json` file in the user's
`$HOME` directory. If this file is found, Genval utilizes it for authentication with the registry. However, if the file is not present,
users must set the `ARTIFACT_REGISTRY_USERNAME` and `ARTIFACT_REGISTRY_PASSWORD` environment variables to authenticate with the container registry.
#### Building, pushing, and signing generated and/or verified config files and OCI artifacts
Expand Down
10 changes: 5 additions & 5 deletions cmd/artifact_pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,22 @@ environment variables to authenticate with the container registry.
and unpack the archive in desired path
# https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
./genval artifact pull --dest oci://ghcr.io/santoshkal/artifacts/genval:test \
./genval artifact pull --dest ghcr.io/santoshkal/artifacts/genval:test \
--path ./output \
--verify true
# User can also pull the artifact by providing the Cosign generated public-key
and unpack the archive in desired path
./genval artifact pull --dest oci://ghcr.io/santoshkal/artifacts/genval:no-sign \
./genval artifact pull --dest ghcr.io/santoshkal/artifacts/genval:no-sign \
--path ./output \
--verify true \
--key ./cosign/cosign.pub
--pub-key ./cosign/cosign.pub
# Uses can also pull the artifact with verifying the signatures of the artifact
in the container registry and unpack the archive in desired path
./genval artifact pull --dest oci://ghcr.io/santoshkal/artifacts/genval:test \
./genval artifact pull --dest ghcr.io/santoshkal/artifacts/genval:test \
--path ./output
`,
RunE: runPullArtifactCmd,
Expand All @@ -68,7 +68,7 @@ func init() {
pullCmd.Flags().StringVarP(&pullArgs.path, "path", "p", "", "path for storing the pulled artifact")
pullCmd.Flags().StringVarP(&pullArgs.dest, "dest", "d", "", "destination URL for pulling the artifact from")
pullCmd.Flags().BoolVarP(&pullArgs.verify, "verify", "v", false, "Set signature verification of the artifact using Sigstore cosign")
pullCmd.Flags().StringVarP(&pullArgs.cosignKey, "key", "k", "", "Cosign public key for varifying the artifact")
pullCmd.Flags().StringVarP(&pullArgs.cosignKey, "pub-key", "k", "", "Cosign public key for varifying the artifact")

artifactCmd.AddCommand(pullCmd)
}
Expand Down
24 changes: 17 additions & 7 deletions cmd/artifact_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"path/filepath"
"time"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/compression"
"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/name"
Expand Down Expand Up @@ -41,15 +40,20 @@ environment variables to authenticate with the container registry.
# Through this workflow, user needs to open th redirectoin link and authorize with OIDC token
./genval artifact push --reqinput ./templates/defaultpolicies/rego \
--url --dest oci://ghcr.io/santoshkal/artifacts/genval:test \
--dest ghcr.io/santoshkal/artifacts/genval:test \
--sign true
# TODO: Add functionality for signing with Cosign genrated pvt key
# Alternatively, users may provide the Cosign generated private key for signing the artifact
./genval artifact push --reqinput ./templates/defaultpolicies/rego \
--dest ghcr.io/santoshkal/artifacts/genval:test \
--sign true
--cosign-key <Path to Cosign private Key>
# User can pass additional annotations in <key=value> pair while pushing the artifact
./genval artifact push --reqinput ./templates/defaultpolicies/rego \
--url --dest oci://ghcr.io/santoshkal/artifacts/genval:test \
--dest ghcr.io/santoshkal/artifacts/genval:test \
--annotations foo=bar
`,
Expand All @@ -61,6 +65,7 @@ type pushFlags struct {
dest string
annotations []string
sign bool
cosignKey string
}

var pushArgs pushFlags
Expand All @@ -76,6 +81,7 @@ func init() {
}
pushCmd.Flags().StringArrayVarP(&pushArgs.annotations, "annotations", "a", nil, "Set custom annotation in <key>=<value> format")
pushCmd.Flags().BoolVarP(&pushArgs.sign, "sign", "s", false, "If set to true, signs the artifact with cosign in keyless mode")
pushCmd.Flags().StringVarP(&pushArgs.cosignKey, "cosign-key", "k", "", "path to cosign private key")
artifactCmd.AddCommand(pushCmd)
}

Expand Down Expand Up @@ -143,11 +149,15 @@ func runPushCmd(cmd *cobra.Command, args []string) error {
if err != nil {
log.Errorf("appending content to artifact failed: %v", err)
}
// TODO: Add userAgent header for HTTP requests made to OCI registry
spin := utils.StartSpinner("pushing artifact")
defer spin.Stop()
opts := crane.WithAuthFromKeychain((authn.DefaultKeychain))
opts, err := oci.GetCreds()
if err != nil {
log.Errorf("Error reading credentials: %v", err)
}

if err := crane.Push(img, ref.String(), opts); err != nil {
if err := crane.Push(img, ref.String(), opts...); err != nil {
log.Fatalf("Error pushing artifact: %v", err)
}
spin.Stop()
Expand All @@ -159,7 +169,7 @@ func runPushCmd(cmd *cobra.Command, args []string) error {
digestURL := ref.Context().Digest(digest.String()).String()

if pushArgs.sign {
err := oci.SignCosign(digestURL)
err := oci.SignCosign(digestURL, pushArgs.cosignKey)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ A user can pass in a JSON file to genval, the passed input will be first evaluat
once input is validated, a Dockerfile will be generated and the generated Dockerfile will be further validated using
the output policies.
Provides flexibility of supplying input files in YAML or JSON formats, as well as policy files for input and output policies.
Genval supports both local file paths or remote URLs, such as those hosted on GitHub (e.g., https://github.com)
Genval Provides flexibility of supplying input files in YAML or JSON formats.All the required input and policy files
for input and output policies can be supplied from local file paths or remote URLs, such as those hosted on GitHub (e.g., https://github.com)
`,
Example: `
# Generating and validating Dockerfile with local files
Expand Down
26 changes: 20 additions & 6 deletions cmd/cuemod_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,34 @@ environment variables to authenticate with the container registry.
`,
Example: `
# Users can initialize the Cue workspace with the following commands to write policies for Kubernetes manifests
# Users can initialize the Cue workspace with the following commands to write policies for Kubernetes manifests and CRD's
and provide the directory to --policy flag in cue command.
./genval cuemod init --tool=k8s
The above command will create all the required files and directories in the workspace for users to write the policies
for validating and generating the Kubernetes resources.
# Similarly available flags for cuemod init are:
# Curently, available flags for cuemod init are:
--tool=k8s:1.29
--tool=argocd:2.10.4
--tool=tektoncd0.58.0
--tool=tektoncd:0.58.0
--too=crosplane:1.15.0
--tool=clusterapi:<version without v>
In case, a user requires a workspace for a tool that is not available in the above list. Genval also supports pulling a custom workspace
created and stored by users in OCI registries. The only requirement while building the workspace is the the directory structure should
exactly be in the following order:
.
├── cue.mod # This directory may contain all Kubernetes types in cue format, generated with "cue get go k8s.io/apis/..."
└── policy.cue
It should contain a cue.mod directory created by Cuelang and a .cue file as a Cue definition.
To generate a cue.mod directory, users may use "cue get go <API Path>" command from the cue CLI as described
here: https://github.com/cue-labs/cue-by-example/tree/main/003_kubernetes_tutorial#arrow_right-generate-kubernetes-cue-schemata
`,
RunE: runInitCmd,
}
Expand Down Expand Up @@ -68,7 +83,6 @@ func runInitCmd(cmd *cobra.Command, args []string) error {
}
// key := ""
verified, err := oci.VerifyArifact(context.Background(), ociURL, initArgs.key)
log.Printf("Verified artifact: %v", verified)
if err != nil {
return fmt.Errorf("error varifying artifact: %v", err)
}
Expand All @@ -86,7 +100,7 @@ func runInitCmd(cmd *cobra.Command, args []string) error {
if input == "y" {
fmt.Println("Proceeding...")

if err := oci.CreateWorkspace(initArgs.tool, desiredTool, ociURL); err != nil {
if err := oci.CreateWorkspace(desiredTool, ociURL); err != nil {
log.Errorf("Error creating workspace: %v", err)
}
log.Infof("Workspace verified and created")
Expand All @@ -96,7 +110,7 @@ func runInitCmd(cmd *cobra.Command, args []string) error {
} else {
fmt.Println("Invalid input. Please enter 'y' or 'n'.")
}
} else if err := oci.CreateWorkspace(initArgs.tool, desiredTool, ociURL); err != nil {
} else if err := oci.CreateWorkspace(desiredTool, ociURL); err != nil {
log.Errorf("Error creating workspace: %v", err)
}
return nil
Expand Down
10 changes: 5 additions & 5 deletions cmd/regoval_dockerfileval.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func init() {
var dockerfilevalCmd = &cobra.Command{
Use: "dockerfileval",
Short: "Validate Dockerfile with Rego policies",
Long: `Using dockerfileval, a user can validate Dockerfilefiles. Provide a Dockerfile thet needs to be validated
Long: `Using dockerfileval, a user can validate Dockerfiles. Provide a Dockerfile thet needs to be validated
to the --reqinput arg and a set of Rego policies in the --policy arg.
The required input Dockerfile and Rego policy files can be either be passed through local file paths or remote URLs,
Expand All @@ -44,14 +44,14 @@ such as those hosted on GitHub (e.g., https://github.com)
# Provide the required files from remote URL's
./genval regoval dockerfileval --reqinput https://raw.githubusercontent.com/intelops/genval-security-policies/patch-1/Dockerfilefile-sample \
--policy https://github.com/intelops/genval-security-policies/blob/patch-1/default-policies/rego/dockerfilefile_policies.rego
./genval regoval dockerfileval --reqinput https://raw.githubusercontent.com/intelops/genval-security-policies/patch-1/Dockerfile-sample \
--policy https://github.com/intelops/genval-security-policies/blob/patch-1/default-policies/rego/dockerfile_policies.rego
# We need to authenticate with GitHub if we intend to pass the required file stired in the GitHub repo
export GITHUB_TOKEN=<your GitHub PAT>
./genval regoval dockerfileval --reqinput https://raw.githubusercontent.com/intelops/genval-security-policies/patch-1/Dockerfilefile-sample \
--policy https://github.com/intelops/genval-security-policies/blob/patch-1/default-policies/rego/dockerfilefile_policies.rego
./genval regoval dockerfileval --reqinput https://raw.githubusercontent.com/intelops/genval-security-policies/patch-1/Dockerfile-sample \
--policy https://github.com/intelops/genval-security-policies/blob/patch-1/default-policies/rego/dockerfile_policies.rego
`,
RunE: runDockerfilevalCmd,
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/showJSON.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ The required input as .tf or a Dockerfile can be either passed through local fil
# We need to authenticate with GitHub if we intend to pass the required file stired in the GitHub repo
export GITHUB_TOKEN=<your GitHub PAT>
./genval showJSON --reqinput https://github.com/intelops/genval-security-policies/blob/patch-1/Dockerfile-sample
./genval showJSON --reqinput hhttps://github.com/intelops/genval-security-policies/blob/patch-1/input-templates/terraform/sec_group.tf
`,
RunE: runshowJSONCmd,
}
Expand Down
25 changes: 14 additions & 11 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ package cmd
import (
"fmt"

"github.com/intelops/genval/pkg/utils"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var (
VERSION = "0.0.1"
versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of Genval",
Long: `All software has versions. This is Genval's`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Genval version: v%v\n", VERSION)
},
}
)
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of Genval",
Long: `All software has versions. This is Genval's`,
Run: func(cmd *cobra.Command, args []string) {
Version, err := utils.GetVersion()
if err != nil {
log.Errorf("Error fetching version info: %v", err)
}
fmt.Println(Version)
},
}

func init() {
rootCmd.AddCommand(versionCmd)
Expand Down
Loading

0 comments on commit 5f6411c

Please sign in to comment.