Skip to content

Commit ba7ce12

Browse files
authored
feat(cli): improve policy output on describe (#1681)
Signed-off-by: Miguel Martinez <[email protected]>
1 parent 52c1782 commit ba7ce12

File tree

3 files changed

+82
-25
lines changed

3 files changed

+82
-25
lines changed

app/cli/cmd/attestation_status.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@ func materialsTable(status *action.AttestationStatusResult, full bool) error {
193193
}
194194
}
195195

196+
evs := status.PolicyEvaluations[m.Name]
197+
if len(evs) > 0 {
198+
mt.AppendRow(table.Row{"Policies", "------"})
199+
policiesTable(evs, mt)
200+
}
201+
196202
mt.AppendSeparator()
197203
}
198204
mt.Render()

app/cli/cmd/workflow_workflow_run_describe.go

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func newWorkflowWorkflowRunDescribeCmd() *cobra.Command {
8282
}
8383

8484
cmd.Flags().StringVar(&runID, "id", "", "workflow Run ID")
85-
cmd.Flags().StringVar(&attestationDigest, "digest", "", "content digest of the attestation")
85+
cmd.Flags().StringVarP(&attestationDigest, "digest", "d", "", "content digest of the attestation")
8686

8787
cmd.Flags().BoolVar(&verifyAttestation, "verify", false, "verify the attestation")
8888
cmd.Flags().StringVar(&publicKey, "key", "", fmt.Sprintf("public key used to verify the attestation. Note: You can also use env variable %s", signingKeyEnvVarName))
@@ -156,6 +156,12 @@ func workflowRunDescribeTableOutput(run *action.WorkflowRunItemFull) error {
156156
gt.AppendRow(table.Row{"", fmt.Sprintf("%s: %s", a.Name, a.Value)})
157157
}
158158
}
159+
160+
evs := att.PolicyEvaluations[chainloop.AttPolicyEvaluation]
161+
if len(evs) > 0 {
162+
gt.AppendRow(table.Row{"Policies", "------"})
163+
policiesTable(evs, gt)
164+
}
159165
gt.Render()
160166

161167
predicateV1Table(att)
@@ -183,7 +189,9 @@ func predicateV1Table(att *action.WorkflowRunAttestationItem) {
183189
if m.Tag != "" {
184190
v = fmt.Sprintf("%s:%s", v, m.Tag)
185191
}
186-
mt.AppendRow(table.Row{"Value", wrap.String(v, 100)})
192+
if v != "" {
193+
mt.AppendRow(table.Row{"Value", wrap.String(v, 100)})
194+
}
187195
}
188196

189197
if m.Hash != "" {
@@ -198,8 +206,7 @@ func predicateV1Table(att *action.WorkflowRunAttestationItem) {
198206
}
199207
evs := att.PolicyEvaluations[m.Name]
200208
if len(evs) > 0 {
201-
mt.AppendSeparator()
202-
mt.AppendRow(table.Row{"Policies"})
209+
mt.AppendRow(table.Row{"Policies", "------"})
203210
policiesTable(evs, mt)
204211
}
205212
mt.AppendSeparator()
@@ -220,29 +227,32 @@ func predicateV1Table(att *action.WorkflowRunAttestationItem) {
220227
}
221228
mt.Render()
222229
}
223-
224-
evs := att.PolicyEvaluations[chainloop.AttPolicyEvaluation]
225-
if len(evs) > 0 {
226-
mt := newTableWriter()
227-
mt.SetTitle("Attestation policies")
228-
policiesTable(evs, mt)
229-
mt.Render()
230-
}
231230
}
232231

233232
func policiesTable(evs []*action.PolicyEvaluation, mt table.Writer) {
234233
for _, ev := range evs {
235-
mt.AppendSeparator()
236-
mt.AppendRow(table.Row{"Policy", ev.Name})
234+
color := text.Colors{text.FgHiRed}
237235
var violations []string
236+
var prefix = ""
238237
if len(ev.Violations) > 0 {
239238
for _, v := range ev.Violations {
240239
violations = append(violations, v.Message)
241240
}
241+
// For multiple violations, we want to indent the list
242+
if len(violations) > 1 {
243+
prefix = "\n - "
244+
}
242245
} else {
243-
violations = append(violations, "None")
246+
violations = append(violations, "Ok")
247+
color = text.Colors{text.FgHiGreen}
244248
}
245-
mt.AppendRow(table.Row{"Violations", fmt.Sprint(strings.Join(violations, "\n"))})
249+
250+
// Color the violations text before joining
251+
for i, v := range violations {
252+
violations[i] = color.Sprint(v)
253+
}
254+
255+
mt.AppendRow(table.Row{"", fmt.Sprintf("%s: %s", ev.Name, prefix+strings.Join(violations, prefix))})
246256
}
247257
}
248258

app/cli/internal/action/attestation_status.go

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,16 @@ type AttestationStatus struct {
4040
}
4141

4242
type AttestationStatusResult struct {
43-
AttestationID string `json:"attestationID"`
44-
InitializedAt *time.Time `json:"initializedAt"`
45-
WorkflowMeta *AttestationStatusWorkflowMeta `json:"workflowMeta"`
46-
Materials []AttestationStatusResultMaterial `json:"materials"`
47-
EnvVars map[string]string `json:"envVars"`
48-
RunnerContext *AttestationResultRunnerContext `json:"runnerContext"`
49-
DryRun bool `json:"dryRun"`
50-
Annotations []*Annotation `json:"annotations"`
51-
IsPushed bool `json:"isPushed"`
43+
AttestationID string `json:"attestationID"`
44+
InitializedAt *time.Time `json:"initializedAt"`
45+
WorkflowMeta *AttestationStatusWorkflowMeta `json:"workflowMeta"`
46+
Materials []AttestationStatusResultMaterial `json:"materials"`
47+
EnvVars map[string]string `json:"envVars"`
48+
RunnerContext *AttestationResultRunnerContext `json:"runnerContext"`
49+
DryRun bool `json:"dryRun"`
50+
Annotations []*Annotation `json:"annotations"`
51+
IsPushed bool `json:"isPushed"`
52+
PolicyEvaluations map[string][]*PolicyEvaluation `json:"policy_evaluations,omitempty"`
5253
}
5354

5455
type AttestationResultRunnerContext struct {
@@ -112,6 +113,18 @@ func (action *AttestationStatus) Run(ctx context.Context, attestationID string)
112113
IsPushed: action.isPushed,
113114
}
114115

116+
// grouped by material name
117+
evaluations := make(map[string][]*PolicyEvaluation)
118+
for _, v := range att.GetPolicyEvaluations() {
119+
if existing, ok := evaluations[v.MaterialName]; ok {
120+
evaluations[v.MaterialName] = append(existing, policyEvaluationStateToActionForStatus(v))
121+
} else {
122+
evaluations[v.MaterialName] = []*PolicyEvaluation{policyEvaluationStateToActionForStatus(v)}
123+
}
124+
}
125+
126+
res.PolicyEvaluations = evaluations
127+
115128
if v := workflowMeta.GetVersion(); v != nil {
116129
res.WorkflowMeta.ProjectVersion = &ProjectVersion{
117130
Version: v.GetVersion(),
@@ -277,3 +290,31 @@ func setMaterialValue(w *v1.Attestation_Material, o *AttestationStatusResultMate
277290

278291
return nil
279292
}
293+
294+
func policyEvaluationStateToActionForStatus(in *v1.PolicyEvaluation) *PolicyEvaluation {
295+
var pr *PolicyReference
296+
if in.PolicyReference != nil {
297+
pr = &PolicyReference{
298+
Name: in.PolicyReference.Name,
299+
}
300+
}
301+
302+
violations := make([]*PolicyViolation, 0, len(in.Violations))
303+
for _, v := range in.Violations {
304+
violations = append(violations, &PolicyViolation{
305+
Subject: v.Subject,
306+
Message: v.Message,
307+
})
308+
}
309+
310+
return &PolicyEvaluation{
311+
Name: in.Name,
312+
MaterialName: in.MaterialName,
313+
Description: in.Description,
314+
Annotations: in.Annotations,
315+
PolicyReference: pr,
316+
Violations: violations,
317+
Skipped: in.Skipped,
318+
SkipReasons: in.SkipReasons,
319+
}
320+
}

0 commit comments

Comments
 (0)