Skip to content

Commit

Permalink
feat: add support to configure local path (chainloop-dev#1542)
Browse files Browse the repository at this point in the history
Signed-off-by: Miguel Martinez <[email protected]>
  • Loading branch information
migmartri authored Nov 19, 2024
1 parent 60adb40 commit 41c5732
Show file tree
Hide file tree
Showing 12 changed files with 41 additions and 15 deletions.
2 changes: 2 additions & 0 deletions app/cli/cmd/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
var (
attAPIToken string
useAttestationRemoteState bool
attestationLocalStatePath string
GracefulExit bool
// attestationID is the unique identifier of the in-progress attestation
// this is required when use-attestation-remote-state is enabled
Expand Down Expand Up @@ -69,6 +70,7 @@ func newAttestationCmd() *cobra.Command {
cobra.CheckErr(cmd.PersistentFlags().MarkHidden("remote-state"))

cmd.PersistentFlags().BoolVar(&GracefulExit, "graceful-exit", false, "exit 0 in case of error. NOTE: this flag will be removed once Chainloop reaches 1.0")
cmd.PersistentFlags().StringVar(&attestationLocalStatePath, "local-state-path", "", "path to store the attestation state locally, default: [tmpDir]/chainloop_attestation.tmp.json")

cmd.AddCommand(newAttestationInitCmd(), newAttestationAddCmd(), newAttestationStatusCmd(), newAttestationPushCmd(), newAttestationResetCmd())

Expand Down
1 change: 1 addition & 0 deletions app/cli/cmd/attestation_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func newAttestationAddCmd() *cobra.Command {
RegistryServer: registryServer,
RegistryUsername: registryUsername,
RegistryPassword: registryPassword,
LocalStatePath: attestationLocalStatePath,
},
)
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion app/cli/cmd/attestation_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func newAttestationInitCmd() *cobra.Command {
DryRun: attestationDryRun,
Force: force,
UseRemoteState: useAttestationRemoteState,
LocalStatePath: attestationLocalStatePath,
},
)
if err != nil {
Expand Down Expand Up @@ -109,7 +110,7 @@ func newAttestationInitCmd() *cobra.Command {
logger.Info().Msg("Attestation initialized! now you can check its status or add materials to it")

// Show the status information
statusAction, err := action.NewAttestationStatus(&action.AttestationStatusOpts{ActionsOpts: actionOpts, UseAttestationRemoteState: useAttestationRemoteState})
statusAction, err := action.NewAttestationStatus(&action.AttestationStatusOpts{ActionsOpts: actionOpts, UseAttestationRemoteState: useAttestationRemoteState, LocalStatePath: attestationLocalStatePath})
if err != nil {
return newGracefulError(err)
}
Expand Down
2 changes: 1 addition & 1 deletion app/cli/cmd/attestation_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func newAttestationPushCmd() *cobra.Command {
a, err := action.NewAttestationPush(&action.AttestationPushOpts{
ActionsOpts: actionOpts, KeyPath: pkPath, BundlePath: bundle,
CLIVersion: info.Version, CLIDigest: info.Digest,
SignServerCAPath: signServerCAPath,
SignServerCAPath: signServerCAPath, LocalStatePath: attestationLocalStatePath,
})
if err != nil {
return fmt.Errorf("failed to load action: %w", err)
Expand Down
4 changes: 2 additions & 2 deletions app/cli/cmd/attestation_reset.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2023 The Chainloop Authors.
// Copyright 2024 The Chainloop Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -41,7 +41,7 @@ func newAttestationResetCmd() *cobra.Command {
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
a, err := action.NewAttestationReset(actionOpts)
a, err := action.NewAttestationReset(&action.AttestationResetOpts{ActionsOpts: actionOpts, LocalStatePath: attestationLocalStatePath})
if err != nil {
return fmt.Errorf("failed to load action: %w", err)
}
Expand Down
1 change: 1 addition & 0 deletions app/cli/cmd/attestation_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func newAttestationStatusCmd() *cobra.Command {
&action.AttestationStatusOpts{
UseAttestationRemoteState: attestationID != "",
ActionsOpts: actionOpts,
LocalStatePath: attestationLocalStatePath,
},
)
if err != nil {
Expand Down
17 changes: 14 additions & 3 deletions app/cli/internal/action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,36 @@ func toTimePtr(t time.Time) *time.Time {
}

// load a crafter with either local or remote state
func newCrafter(enableRemoteState bool, conn *grpc.ClientConn, opts ...crafter.NewOpt) (*crafter.Crafter, error) {

type newCrafterStateOpts struct {
enableRemoteState bool
localStatePath string
}

func newCrafter(stateOpts *newCrafterStateOpts, conn *grpc.ClientConn, opts ...crafter.NewOpt) (*crafter.Crafter, error) {
var stateManager crafter.StateManager
var err error

if stateOpts == nil {
return nil, fmt.Errorf("missing state manager options")
}

// run opts to extract logger
c := &crafter.Crafter{}
for _, opt := range opts {
_ = opt(c)
}

switch enableRemoteState {
switch stateOpts.enableRemoteState {
case true:
stateManager, err = remote.New(pb.NewAttestationStateServiceClient(conn), c.Logger)
case false:
attestationStatePath := filepath.Join(os.TempDir(), "chainloop-attestation.tmp.json")
if path := os.Getenv("CHAINLOOP_ATTESTATION_STATE_PATH"); path != "" {
if path := stateOpts.localStatePath; path != "" {
attestationStatePath = path
}

c.Logger.Debug().Str("path", attestationStatePath).Msg("using local state")
stateManager, err = filesystem.New(attestationStatePath)
}

Expand Down
5 changes: 4 additions & 1 deletion app/cli/internal/action/attestation_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type AttestationAddOpts struct {
ConnectionInsecure bool
// OCI registry credentials used for CONTAINER_IMAGE material type
RegistryServer, RegistryUsername, RegistryPassword string
LocalStatePath string
}

type newCrafterOpts struct {
Expand All @@ -49,6 +50,7 @@ type AttestationAdd struct {
// optional CA certificate for the CAS connection
casCAPath string
connectionInsecure bool
localStatePath string
*newCrafterOpts
}

Expand All @@ -65,14 +67,15 @@ func NewAttestationAdd(cfg *AttestationAddOpts) (*AttestationAdd, error) {
casURI: cfg.CASURI,
casCAPath: cfg.CASCAPath,
connectionInsecure: cfg.ConnectionInsecure,
localStatePath: cfg.LocalStatePath,
}, nil
}

var ErrAttestationNotInitialized = errors.New("attestation not yet initialized")

func (action *AttestationAdd) Run(ctx context.Context, attestationID, materialName, materialValue, materialType string, annotations map[string]string) error {
// initialize the crafter. If attestation-id is provided we assume the attestation is performed using remote state
crafter, err := newCrafter(attestationID != "", action.CPConnection, action.newCrafterOpts.opts...)
crafter, err := newCrafter(&newCrafterStateOpts{enableRemoteState: (attestationID != ""), localStatePath: action.localStatePath}, action.CPConnection, action.newCrafterOpts.opts...)
if err != nil {
return fmt.Errorf("failed to load crafter: %w", err)
}
Expand Down
3 changes: 2 additions & 1 deletion app/cli/internal/action/attestation_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type AttestationInitOpts struct {
// since it's a protection to make sure you don't override the state by mistake
Force bool
UseRemoteState bool
LocalStatePath string
}

type AttestationInit struct {
Expand All @@ -58,7 +59,7 @@ func (e ErrRunnerContextNotFound) Error() string {
}

func NewAttestationInit(cfg *AttestationInitOpts) (*AttestationInit, error) {
c, err := newCrafter(cfg.UseRemoteState, cfg.CPConnection, crafter.WithLogger(&cfg.Logger))
c, err := newCrafter(&newCrafterStateOpts{enableRemoteState: cfg.UseRemoteState, localStatePath: cfg.LocalStatePath}, cfg.CPConnection, crafter.WithLogger(&cfg.Logger))
if err != nil {
return nil, fmt.Errorf("failed to load crafter: %w", err)
}
Expand Down
7 changes: 5 additions & 2 deletions app/cli/internal/action/attestation_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type AttestationPushOpts struct {
KeyPath, CLIVersion, CLIDigest, BundlePath string

SignServerCAPath string
LocalStatePath string
}

type AttestationResult struct {
Expand All @@ -47,6 +48,7 @@ type AttestationPush struct {
*ActionsOpts
keyPath, cliVersion, cliDigest, bundlePath string
signServerCAPath string
localStatePath string
*newCrafterOpts
}

Expand All @@ -59,14 +61,15 @@ func NewAttestationPush(cfg *AttestationPushOpts) (*AttestationPush, error) {
cliDigest: cfg.CLIDigest,
bundlePath: cfg.BundlePath,
signServerCAPath: cfg.SignServerCAPath,
localStatePath: cfg.LocalStatePath,
newCrafterOpts: &newCrafterOpts{cpConnection: cfg.CPConnection, opts: opts},
}, nil
}

func (action *AttestationPush) Run(ctx context.Context, attestationID string, runtimeAnnotations map[string]string) (*AttestationResult, error) {
useRemoteState := attestationID != ""
// initialize the crafter. If attestation-id is provided we assume the attestation is performed using remote state
crafter, err := newCrafter(useRemoteState, action.CPConnection, action.newCrafterOpts.opts...)
crafter, err := newCrafter(&newCrafterStateOpts{enableRemoteState: useRemoteState, localStatePath: action.localStatePath}, action.CPConnection, action.newCrafterOpts.opts...)
if err != nil {
return nil, fmt.Errorf("failed to load crafter: %w", err)
}
Expand All @@ -79,7 +82,7 @@ func (action *AttestationPush) Run(ctx context.Context, attestationID string, ru

// Retrieve attestation status
statusAction, err := NewAttestationStatus(&AttestationStatusOpts{
ActionsOpts: action.ActionsOpts, UseAttestationRemoteState: useRemoteState, isPushed: true,
ActionsOpts: action.ActionsOpts, UseAttestationRemoteState: useRemoteState, isPushed: true, LocalStatePath: action.localStatePath,
})

if err != nil {
Expand Down
8 changes: 5 additions & 3 deletions app/cli/internal/action/attestation_reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,24 @@ const AttestationResetTriggerCancelled = "cancellation"

type AttestationResetOpts struct {
*ActionsOpts
LocalStatePath string
}

type AttestationReset struct {
*ActionsOpts
*newCrafterOpts
localStatePath string
}

func NewAttestationReset(cfg *ActionsOpts) (*AttestationReset, error) {
func NewAttestationReset(cfg *AttestationResetOpts) (*AttestationReset, error) {
return &AttestationReset{
newCrafterOpts: &newCrafterOpts{cpConnection: cfg.CPConnection, opts: []crafter.NewOpt{crafter.WithLogger(&cfg.Logger)}},
ActionsOpts: cfg}, nil
ActionsOpts: cfg.ActionsOpts, localStatePath: cfg.LocalStatePath}, nil
}

func (action *AttestationReset) Run(ctx context.Context, attestationID, trigger, reason string) error {
// initialize the crafter. If attestation-id is provided we assume the attestation is performed using remote state
crafter, err := newCrafter(attestationID != "", action.CPConnection, action.newCrafterOpts.opts...)
crafter, err := newCrafter(&newCrafterStateOpts{enableRemoteState: attestationID != "", localStatePath: action.localStatePath}, action.CPConnection, action.newCrafterOpts.opts...)
if err != nil {
return fmt.Errorf("failed to load crafter: %w", err)
}
Expand Down
3 changes: 2 additions & 1 deletion app/cli/internal/action/attestation_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type AttestationStatusOpts struct {
*ActionsOpts
UseAttestationRemoteState bool
isPushed bool
LocalStatePath string
}

type AttestationStatus struct {
Expand Down Expand Up @@ -66,7 +67,7 @@ type AttestationStatusResultMaterial struct {
}

func NewAttestationStatus(cfg *AttestationStatusOpts) (*AttestationStatus, error) {
c, err := newCrafter(cfg.UseAttestationRemoteState, cfg.CPConnection, crafter.WithLogger(&cfg.Logger))
c, err := newCrafter(&newCrafterStateOpts{enableRemoteState: cfg.UseAttestationRemoteState, localStatePath: cfg.LocalStatePath}, cfg.CPConnection, crafter.WithLogger(&cfg.Logger))
if err != nil {
return nil, fmt.Errorf("failed to load crafter: %w", err)
}
Expand Down

0 comments on commit 41c5732

Please sign in to comment.