Skip to content

Commit f6c8f0b

Browse files
authored
Added policy flag to assert artifact server/#3740 (#550)
* Added policy flag to assert artifact server/#3740
1 parent 2bf863e commit f6c8f0b

4 files changed

Lines changed: 43 additions & 1 deletion

File tree

cmd/kosli/assertArtifact.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type assertArtifactOptions struct {
4646
fingerprint string // This is calculated or provided by the user
4747
flowName string
4848
envName string
49+
policyNames []string
4950
output string
5051
}
5152

@@ -78,6 +79,7 @@ func newAssertArtifactCmd(out io.Writer) *cobra.Command {
7879
cmd.Flags().StringVarP(&o.flowName, "flow", "f", "", flowNameFlag)
7980
cmd.Flags().StringVar(&o.envName, "environment", "", envNameFlag)
8081
cmd.Flags().StringVarP(&o.output, "output", "o", "table", outputFlag)
82+
cmd.Flags().StringSliceVar(&o.policyNames, "policy", []string{}, policyName)
8183

8284
addFingerprintFlags(cmd, o.fingerprintOptions)
8385
addDryRunFlag(cmd)
@@ -105,6 +107,12 @@ func (o *assertArtifactOptions) run(out io.Writer, args []string) error {
105107
params.Add("environment_name", o.envName)
106108
}
107109

110+
if len(o.policyNames) > 0 {
111+
for _, policy := range o.policyNames {
112+
params.Add("policy_name", policy)
113+
}
114+
}
115+
108116
fullURL := baseURL
109117
if len(params) > 0 {
110118
fullURL += "?" + params.Encode()
@@ -162,7 +170,7 @@ func printAssertAsTable(raw string, out io.Writer, page int) error {
162170

163171
logger.Info(" %-32v %-30v %-15v %-10v %-10v", name, attType, status, isCompliant, unexpectedStr)
164172
}
165-
if scope == "environment" {
173+
if scope == "environment" || scope == "policy" {
166174
logger.Info("%-32v %-30v", "Policy-name", "status")
167175
policyEvaluations := evaluationResult["policy_evaluations"].([]interface{})
168176
for _, item := range policyEvaluations {

cmd/kosli/assertArtifact_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ type AssertArtifactCommandTestSuite struct {
1616
defaultKosliArguments string
1717
flowName string
1818
envName string
19+
policyName1 string
20+
policyName2 string
1921
artifactName string
2022
artifactPath string
2123
fingerprint string
@@ -24,6 +26,8 @@ type AssertArtifactCommandTestSuite struct {
2426
func (suite *AssertArtifactCommandTestSuite) SetupTest() {
2527
suite.flowName = "assert-artifact"
2628
suite.envName = "assert-artifact-environment"
29+
suite.policyName1 = "assert-artifact-policy-1"
30+
suite.policyName2 = "assert-artifact-policy-2"
2731
suite.artifactName = "arti"
2832
suite.artifactPath = "testdata/folder1/hello.txt"
2933
global = &GlobalOpts{
@@ -38,6 +42,8 @@ func (suite *AssertArtifactCommandTestSuite) SetupTest() {
3842
artifactType: "file",
3943
}
4044
CreateEnv(global.Org, suite.envName, "server", suite.Suite.T())
45+
CreatePolicy(global.Org, suite.policyName1, suite.Suite.T())
46+
CreatePolicy(global.Org, suite.policyName2, suite.Suite.T())
4147
var err error
4248
suite.fingerprint, err = GetSha256Digest(suite.artifactPath, fingerprintOptions, logger)
4349
require.NoError(suite.Suite.T(), err)
@@ -68,6 +74,11 @@ func (suite *AssertArtifactCommandTestSuite) TestAssertArtifactCmd() {
6874
cmd: fmt.Sprintf(`assert artifact --fingerprint %s --flow %s --environment %s %s`, suite.fingerprint, suite.flowName, suite.envName, suite.defaultKosliArguments),
6975
goldenRegex: "(?s)^COMPLIANT\n.*Attestation-name.*Policy-name.*See more details at http://localhost(:8001)?/docs-cmd-test-user/flows/assert-artifact/artifacts/fcf33337634c2577a5d86fd7ecb0a25a7c1bb5d89c14fd236f546a5759252c02(?:\\?artifact_id=[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{8})?\n",
7076
},
77+
{
78+
name: "asserting an existing compliant artifact (using --fingerprint) for an policy results in OK and zero exit",
79+
cmd: fmt.Sprintf(`assert artifact --fingerprint %s --flow %s --policy %s %s`, suite.fingerprint, suite.flowName, suite.policyName1, suite.defaultKosliArguments),
80+
goldenRegex: "(?s)^COMPLIANT\n.*Attestation-name.*Policy-name.*assert-artifact-policy-1.*See more details at http://localhost(:8001)?/docs-cmd-test-user/flows/assert-artifact/artifacts/fcf33337634c2577a5d86fd7ecb0a25a7c1bb5d89c14fd236f546a5759252c02(?:\\?artifact_id=[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{8})?\n",
81+
},
7182
{
7283
name: "asserting an existing compliant artifact (using --artifact-type) results in OK and zero exit",
7384
cmd: fmt.Sprintf(`assert artifact %s --artifact-type file --flow %s %s`, suite.artifactPath, suite.flowName, suite.defaultKosliArguments),
@@ -81,6 +92,16 @@ func (suite *AssertArtifactCommandTestSuite) TestAssertArtifactCmd() {
8192
{"scope", "flow"},
8293
},
8394
},
95+
{
96+
name: "json output of asserting an existing compliant artifact (using --fingerprint) for an policy results in correct json",
97+
cmd: fmt.Sprintf(`assert artifact %s --output json --artifact-type file --flow %s --policy=%s --policy=%s %s`, suite.artifactPath, suite.flowName, suite.policyName1, suite.policyName2, suite.defaultKosliArguments),
98+
goldenJson: []jsonCheck{
99+
{"compliant", true},
100+
{"scope", "policy"},
101+
{"policy_evaluations", "length:2"},
102+
{"policy_evaluations.[0].policy_name", suite.policyName1},
103+
{"policy_evaluations.[1].policy_name", suite.policyName2}},
104+
},
84105
{
85106
wantError: true,
86107
name: "not providing --fingerprint nor --artifact-type fails",

cmd/kosli/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ The ^.kosli_ignore^ will be treated as part of the artifact like any other file,
234234
policyDescriptionFlag = "[optional] policy description."
235235
policyCommentFlag = "[optional] comment about the change made in a policy file when updating a policy."
236236
policyTypeFlag = "[defaulted] the type of policy. One of: [env]"
237+
policyName = "[optional] policy name (can be specified multiple times)"
237238
attachPolicyEnvFlag = "the list of environment names to attach the policy to"
238239
detachPolicyEnvFlag = "the list of environment names to detach the policy from"
239240
sonarAPITokenFlag = "[required] SonarCloud/SonarQube API token."

cmd/kosli/testHelpers.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,18 @@ func goldenJsonContains(t *testing.T, output string, path string, want interface
162162
}
163163
}
164164

165+
// Special case: check array length
166+
if wantStr, ok := want.(string); ok && strings.HasPrefix(wantStr, "length:") {
167+
lengthStr := strings.TrimPrefix(wantStr, "length:")
168+
expectedLength, err := strconv.Atoi(lengthStr)
169+
require.NoError(t, err, "invalid length specification: %s", wantStr)
170+
171+
list, ok := current.([]interface{})
172+
require.True(t, ok, "expected array at path %s", path)
173+
require.Equal(t, expectedLength, len(list), "unexpected array length at path %s", path)
174+
return
175+
}
176+
165177
require.Equal(t, want, current, "unexpected value at path %s", path)
166178
}
167179

0 commit comments

Comments
 (0)