Skip to content

Commit c9048da

Browse files
acornett21bcrochet
authored andcommitted
adding a new policy that allows scratch and root policy exceptions at the same time
Signed-off-by: Adam D. Cornett <[email protected]>
1 parent 80b05fd commit c9048da

File tree

11 files changed

+84
-19
lines changed

11 files changed

+84
-19
lines changed

cmd/preflight/cmd/list_checks.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ func printChecks(w io.Writer) {
3434
fmt.Fprintln(w, formattedPolicyBlock("Container", engine.ContainerPolicy(context.TODO()), "invoked on container images"))
3535
fmt.Fprintln(w, formattedPolicyBlock("Container Root Exception", engine.RootExceptionContainerPolicy(context.TODO()),
3636
"automatically applied for container images if preflight determines a root exception flag has been added to your Red Hat Connect project"))
37-
fmt.Fprintln(w, formattedPolicyBlock("Container Scratch Exception", engine.ScratchContainerPolicy(context.TODO()),
37+
fmt.Fprintln(w, formattedPolicyBlock("Container Scratch (NonRoot) Exception", engine.ScratchNonRootContainerPolicy(context.TODO()),
3838
"automatically applied for container checks if preflight determines a scratch exception flag has been added to your Red Hat Connect project"))
39+
fmt.Fprintln(w, formattedPolicyBlock("Container Scratch (Root) Exception", engine.ScratchRootContainerPolicy(context.TODO()),
40+
"automatically applied for container checks if preflight determines scratch and root exception flags have both been added to your Red Hat Connect project"))
3941
}
4042

4143
// formattedPolicyBlock accepts information about the checklist

cmd/preflight/cmd/list_checks_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ var _ = Describe("list checks subcommand", func() {
6565
})
6666

6767
It("should always contain the scratch exception policy", func() {
68-
expected := formatList(engine.ScratchContainerPolicy(context.TODO()))
68+
expected := formatList(engine.ScratchNonRootContainerPolicy(context.TODO()))
6969
buf := strings.Builder{}
7070
printChecks(&buf)
7171

container/check_container.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func (c *containerCheck) Run(ctx context.Context) (certification.Results, error)
4646
cfg := runtime.Config{
4747
Image: c.image,
4848
DockerConfig: c.dockerconfigjson,
49-
Scratch: c.policy == policy.PolicyScratch,
49+
Scratch: c.policy == policy.PolicyScratchNonRoot || c.policy == policy.PolicyScratchRoot,
5050
Bundle: false,
5151
Insecure: c.insecure,
5252
Platform: c.platform,

internal/engine/engine.go

+18-5
Original file line numberDiff line numberDiff line change
@@ -784,14 +784,21 @@ func InitializeContainerChecks(ctx context.Context, p policy.Policy, cfg Contain
784784
cfg.CertificationProjectID,
785785
&http.Client{Timeout: 60 * time.Second})),
786786
}, nil
787-
case policy.PolicyScratch:
787+
case policy.PolicyScratchNonRoot:
788788
return []check.Check{
789789
&containerpol.HasLicenseCheck{},
790790
containerpol.NewHasUniqueTagCheck(cfg.DockerConfig),
791791
&containerpol.MaxLayersCheck{},
792792
&containerpol.HasRequiredLabelsCheck{},
793793
&containerpol.RunAsNonRootCheck{},
794794
}, nil
795+
case policy.PolicyScratchRoot:
796+
return []check.Check{
797+
&containerpol.HasLicenseCheck{},
798+
containerpol.NewHasUniqueTagCheck(cfg.DockerConfig),
799+
&containerpol.MaxLayersCheck{},
800+
&containerpol.HasRequiredLabelsCheck{},
801+
}, nil
795802
}
796803

797804
return nil, fmt.Errorf("provided container policy %s is unknown", p)
@@ -812,7 +819,7 @@ func makeCheckList(checks []check.Check) []string {
812819
func checkNamesFor(ctx context.Context, p policy.Policy) []string {
813820
var c []check.Check
814821
switch p {
815-
case policy.PolicyContainer, policy.PolicyRoot, policy.PolicyScratch:
822+
case policy.PolicyContainer, policy.PolicyRoot, policy.PolicyScratchNonRoot, policy.PolicyScratchRoot:
816823
c, _ = InitializeContainerChecks(ctx, p, ContainerCheckConfig{})
817824
case policy.PolicyOperator:
818825
c, _ = InitializeOperatorChecks(ctx, p, OperatorCheckConfig{})
@@ -833,10 +840,16 @@ func ContainerPolicy(ctx context.Context) []string {
833840
return checkNamesFor(ctx, policy.PolicyContainer)
834841
}
835842

836-
// ScratchContainerPolicy returns the names of checks in the
843+
// ScratchNonRootContainerPolicy returns the names of checks in the
837844
// container policy with scratch exception.
838-
func ScratchContainerPolicy(ctx context.Context) []string {
839-
return checkNamesFor(ctx, policy.PolicyScratch)
845+
func ScratchNonRootContainerPolicy(ctx context.Context) []string {
846+
return checkNamesFor(ctx, policy.PolicyScratchNonRoot)
847+
}
848+
849+
// ScratchRootContainerPolicy returns the names of checks in the
850+
// container policy with scratch and root exception.
851+
func ScratchRootContainerPolicy(ctx context.Context) []string {
852+
return checkNamesFor(ctx, policy.PolicyScratchRoot)
840853
}
841854

842855
// RootExceptionContainerPolicy returns the names of checks in the

internal/engine/engine_test.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,11 @@ var _ = Describe("Check Initialization", func() {
300300
Expect(err).ToNot(HaveOccurred())
301301
})
302302
It("should properly return checks for the scratch policy", func() {
303-
_, err := InitializeContainerChecks(context.TODO(), policy.PolicyScratch, ContainerCheckConfig{})
303+
_, err := InitializeContainerChecks(context.TODO(), policy.PolicyScratchNonRoot, ContainerCheckConfig{})
304+
Expect(err).ToNot(HaveOccurred())
305+
})
306+
It("should properly return checks for the scratch and root policy", func() {
307+
_, err := InitializeContainerChecks(context.TODO(), policy.PolicyScratchRoot, ContainerCheckConfig{})
304308
Expect(err).ToNot(HaveOccurred())
305309
})
306310
It("should properly return checks for the root policy", func() {
@@ -353,13 +357,19 @@ var _ = Describe("Check Name Queries", func() {
353357
"FollowsRestrictedNetworkEnablementGuidelines",
354358
"RequiredAnnotations",
355359
}),
356-
Entry("scratch container policy", ScratchContainerPolicy, []string{
360+
Entry("scratch container policy", ScratchNonRootContainerPolicy, []string{
357361
"HasLicense",
358362
"HasUniqueTag",
359363
"LayerCountAcceptable",
360364
"HasRequiredLabel",
361365
"RunAsNonRoot",
362366
}),
367+
Entry("scratch container policy", ScratchRootContainerPolicy, []string{
368+
"HasLicense",
369+
"HasUniqueTag",
370+
"LayerCountAcceptable",
371+
"HasRequiredLabel",
372+
}),
363373
Entry("root container policy", RootExceptionContainerPolicy, []string{
364374
"HasLicense",
365375
"HasUniqueTag",

internal/lib/fakes_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,17 @@ func gpFuncReturnRootException(ctx context.Context) (*pyxis.CertProject, error)
157157
}, nil
158158
}
159159

160+
// gpFuncReturnScratchRootException implements gpFunc and returns a root exception.
161+
func gpFuncReturnScratchRootException(ctx context.Context) (*pyxis.CertProject, error) {
162+
return &pyxis.CertProject{
163+
Container: pyxis.Container{
164+
DockerConfigJSON: "",
165+
OsContentType: "Scratch Image",
166+
Privileged: true,
167+
},
168+
}, nil
169+
}
170+
160171
// gpFuncReturnNoException implements gpFunc and returns no exception indicators.
161172
func gpFuncReturnNoException(ctx context.Context) (*pyxis.CertProject, error) {
162173
return &pyxis.CertProject{

internal/lib/lib.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,17 @@ func GetContainerPolicyExceptions(ctx context.Context, pc PyxisClient) (policy.P
3939
return "", fmt.Errorf("could not retrieve project: %w", err)
4040
}
4141
logger.V(log.DBG).Info("certification project", "name", certProject.Name)
42+
43+
// if the partner has gotten a scratch exception from the business and os_content_type == "Scratch Image"
44+
// and a partner sets `Host Level Access` in connect to `Privileged`, enable ScratchRootContainerPolicy checks
45+
if certProject.ScratchProject() && certProject.Container.Privileged {
46+
return policy.PolicyScratchRoot, nil
47+
}
48+
49+
// if the partner has gotten a scratch exception from the business and os_content_type == "Scratch Image",
50+
// enable ScratchNonRootContainerPolicy checks
4251
if certProject.ScratchProject() {
43-
return policy.PolicyScratch, nil
52+
return policy.PolicyScratchNonRoot, nil
4453
}
4554

4655
// if a partner sets `Host Level Access` in connect to `Privileged`, enable RootExceptionContainerPolicy checks

internal/lib/types.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,12 @@ func (s *ContainerCertificationSubmitter) Submit(ctx context.Context) error {
161161
pol := policy.PolicyContainer
162162

163163
if certProject.ScratchProject() {
164-
pol = policy.PolicyScratch
164+
pol = policy.PolicyScratchNonRoot
165165
}
166166

167167
// only read the rpm manifest file off of disk if the policy executed is not scratch
168168
// scratch images do not have rpm manifests, the rpm-manifest.json file is not written to disk by the engine during execution
169-
if pol != policy.PolicyScratch {
169+
if pol != policy.PolicyScratchNonRoot {
170170
rpmManifest, err := os.Open(path.Join(artifactWriter.Path(), check.DefaultRPMManifestFilename))
171171
if err != nil {
172172
return fmt.Errorf(

internal/lib/types_test.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,14 @@ var _ = Describe("Policy Resolution", func() {
7474
It("should return a scratch policy exception if the project has type flag in the API", func() {
7575
fakePC.getProjectsFunc = gpFuncReturnScratchException
7676
p, err := GetContainerPolicyExceptions(context.TODO(), fakePC)
77-
Expect(p).To(Equal(policy.PolicyScratch))
77+
Expect(p).To(Equal(policy.PolicyScratchNonRoot))
7878
Expect(err).ToNot(HaveOccurred())
7979
})
8080

8181
It("should return a scratch policy exception if the project has os_content_type flag in the API", func() {
8282
fakePC.getProjectsFunc = gpFuncReturnScratchImageException
8383
p, err := GetContainerPolicyExceptions(context.TODO(), fakePC)
84-
Expect(p).To(Equal(policy.PolicyScratch))
84+
Expect(p).To(Equal(policy.PolicyScratchNonRoot))
8585
Expect(err).ToNot(HaveOccurred())
8686
})
8787

@@ -92,6 +92,13 @@ var _ = Describe("Policy Resolution", func() {
9292
Expect(err).ToNot(HaveOccurred())
9393
})
9494

95+
It("should return a scratch plus root policy exception if the project has the flag in the API", func() {
96+
fakePC.getProjectsFunc = gpFuncReturnScratchRootException
97+
p, err := GetContainerPolicyExceptions(context.TODO(), fakePC)
98+
Expect(p).To(Equal(policy.PolicyScratchRoot))
99+
Expect(err).ToNot(HaveOccurred())
100+
})
101+
95102
It("should return a container policy exception if the project no exceptions in the API", func() {
96103
fakePC.getProjectsFunc = gpFuncReturnNoException
97104
p, err := GetContainerPolicyExceptions(context.TODO(), fakePC)

internal/policy/policy.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ package policy
33
type Policy = string
44

55
const (
6-
PolicyOperator Policy = "operator"
7-
PolicyContainer Policy = "container"
8-
PolicyScratch Policy = "scratch"
9-
PolicyRoot Policy = "root"
6+
PolicyOperator Policy = "operator"
7+
PolicyContainer Policy = "container"
8+
PolicyScratchNonRoot Policy = "scratch-nonroot"
9+
PolicyScratchRoot Policy = "scratch-root"
10+
PolicyRoot Policy = "root"
1011
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
FROM scratch
2+
3+
COPY example-license.txt /licenses/
4+
5+
LABEL name="preflight test image scratch plus root container-policy" \
6+
vendor="preflight test vendor" \
7+
version="1" \
8+
release="1" \
9+
summary="testing the preflight tool" \
10+
description="test the preflight tool"
11+
12+
USER root

0 commit comments

Comments
 (0)