Skip to content

Commit

Permalink
policy: add PolicyScratchRoot
Browse files Browse the repository at this point in the history
Scratch projects might run privileged and, thus, introduce a new
policy based on the scratch policy but without checking for
RunAsNonRoot.

Co-authored-by: Adam D. Cornett <adc@redhat.com>
Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com>
  • Loading branch information
hbrueckner and acornett21 committed Sep 6, 2022
1 parent 7919147 commit 38b241f
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 0 deletions.
13 changes: 13 additions & 0 deletions certification/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ func initializeChecks(ctx context.Context, p policy.Policy, cfg certification.Co
&containerpol.HasRequiredLabelsCheck{},
&containerpol.RunAsNonRootCheck{},
}, nil
case policy.PolicyScratchRoot:
return []certification.Check{
&containerpol.HasLicenseCheck{},
containerpol.NewHasUniqueTagCheck(cfg.DockerConfig()),
&containerpol.MaxLayersCheck{},
&containerpol.HasRequiredLabelsCheck{},
}, nil
}

return nil, fmt.Errorf("provided policy %s is unknown", p)
Expand Down Expand Up @@ -144,6 +151,12 @@ func ScratchNonRootContainerPolicy(ctx context.Context) []string {
return checkNamesFor(ctx, policy.PolicyScratchNonRoot)
}

// ScratchRootContainerPolicy returns the names of checks in the
// container policy with scratch and root exception.
func ScratchRootContainerPolicy(ctx context.Context) []string {
return checkNamesFor(ctx, policy.PolicyScratchRoot)
}

// RootExceptionContainerPolicy returns the names of checks in the
// container policy with root exception.
func RootExceptionContainerPolicy(ctx context.Context) []string {
Expand Down
23 changes: 23 additions & 0 deletions certification/engine/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,29 @@ var _ = Describe("Engine Creation", func() {
})
})

Context("for the scratch and root policy", func() {
cfg := runtime.Config{
Image: "dummy/image",
Policy: policy.PolicyScratchRoot,
ResponseFormat: "json",
}

It("should return an engine and no error", func() {
engine, err := NewForConfig(context.TODO(), cfg.ReadOnly())
Expect(err).ToNot(HaveOccurred())
Expect(engine).ToNot(BeNil())
})
It("should return the correct names", func() {
names := ScratchRootContainerPolicy(context.TODO())
Expect(names).To(ContainElements([]string{
"HasLicense",
"HasUniqueTag",
"LayerCountAcceptable",
"HasRequiredLabel",
}))
})
})

Context("for the Root policy", func() {
cfg := runtime.Config{
Image: "dummy/image",
Expand Down
1 change: 1 addition & 0 deletions certification/policy/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ const (
PolicyOperator Policy = "operator"
PolicyContainer Policy = "container"
PolicyScratchNonRoot Policy = "scratch-nonroot"
PolicyScratchRoot Policy = "scratch-root"
PolicyRoot Policy = "root"
)
3 changes: 3 additions & 0 deletions cmd/check_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ func getContainerPolicyExceptions(ctx context.Context, pc pyxisClient) (policy.P
}
log.Debugf("Certification project name is: %s", certProject.Name)
if certProject.Container.Type == "scratch" {
if certProject.Container.Privileged {
return policy.PolicyScratchRoot, nil
}
return policy.PolicyScratchNonRoot, nil
}

Expand Down
7 changes: 7 additions & 0 deletions cmd/check_container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ var _ = Describe("Check Container Command", func() {
Expect(err).ToNot(HaveOccurred())
})

It("should return a scratch and root policy exception if the project has the flag in the API", func() {
fakePC.getProjectsFunc = gpFuncReturnScratchRootException
p, err := getContainerPolicyExceptions(context.TODO(), fakePC)
Expect(p).To(Equal(policy.PolicyScratchRoot))
Expect(err).ToNot(HaveOccurred())
})

It("should return a root policy exception if the project has the flag in the API", func() {
fakePC.getProjectsFunc = gpFuncReturnRootException
p, err := getContainerPolicyExceptions(context.TODO(), fakePC)
Expand Down
11 changes: 11 additions & 0 deletions cmd/fakes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,17 @@ func gpFuncReturnScratchNonRootException(ctx context.Context) (*pyxis.CertProjec
}, nil
}

// gpFuncReturnScratchRootException implements gpFunc and returns a scratch
// and root exception.
func gpFuncReturnScratchRootException(ctx context.Context) (*pyxis.CertProject, error) {
return &pyxis.CertProject{
Container: pyxis.Container{
Type: "scratch",
Privileged: true,
},
}, nil
}

// gpFuncReturnRootException implements gpFunc and returns a root exception.
func gpFuncReturnRootException(ctx context.Context) (*pyxis.CertProject, error) {
return &pyxis.CertProject{
Expand Down
2 changes: 2 additions & 0 deletions cmd/list_checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ func printChecks(w io.Writer) {
"automatically applied for container images if preflight determines a root exception flag has been added to your Red Hat Connect project"))
fmt.Fprintln(w, formattedPolicyBlock("Container Scratch (NonRoot) Exception", engine.ScratchNonRootContainerPolicy(context.TODO()),
"automatically applied for container checks if preflight determines a scratch exception flag has been added to your Red Hat Connect project"))
fmt.Fprintln(w, formattedPolicyBlock("Container Scratch (Root) Exception", engine.ScratchRootContainerPolicy(context.TODO()),
"automatically applied for container checks if preflight determines a scratch and root exception flags have been added to your Red Hat Connect project"))
}

// formattedPolicyBlock accepts information about the checklist
Expand Down
8 changes: 8 additions & 0 deletions cmd/list_checks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ var _ = Describe("list checks subcommand", func() {

Expect(buf.String()).To(ContainSubstring(expected))
})

It("should always contain the scratch and root exception policy", func() {
expected := formatList(engine.ScratchRootContainerPolicy(context.TODO()))
buf := strings.Builder{}
printChecks(&buf)

Expect(buf.String()).To(ContainSubstring(expected))
})
})

Context("When executing the cobra command", func() {
Expand Down

0 comments on commit 38b241f

Please sign in to comment.