Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Gator sync test support #3098

Merged
merged 45 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
1ea86c3
initial setup
anlandu Sep 19, 2023
434523e
Tests etc
anlandu Oct 21, 2023
004dd3e
Remove create cmd
anlandu Oct 21, 2023
5904f35
Merge branch 'master' into gator-sync-support
anlandu Oct 21, 2023
0e3b88c
Update gator.md
anlandu Oct 21, 2023
2517785
Lint
anlandu Oct 23, 2023
60d43c2
Merge branch 'master' into gator-sync-support
anlandu Oct 23, 2023
578c233
Merge branch 'gator-sync-support' of https://github.com/anlandu/gatek…
anlandu Oct 23, 2023
7d398a2
Update gator.md
anlandu Oct 23, 2023
ace0122
Merge branch 'master' into gator-sync-support
anlandu Oct 23, 2023
9af46d1
Comments
anlandu Oct 23, 2023
4ccceac
Merge branch 'gator-sync-support' of https://github.com/anlandu/gatek…
anlandu Oct 23, 2023
1bf831a
Continue on err
anlandu Oct 23, 2023
aafc019
Merge branch 'master' into gator-sync-support
anlandu Oct 23, 2023
218e58b
Comments
anlandu Nov 3, 2023
0fc5c29
Merge branch 'gator-sync-support' of https://github.com/anlandu/gatek…
anlandu Nov 4, 2023
e798bfd
Marshal supported GVKs up front
anlandu Nov 4, 2023
7f7f3d9
lint
anlandu Nov 4, 2023
bea82ab
Merge branch 'master' into gator-sync-support
anlandu Nov 4, 2023
1431bb9
Comments
anlandu Nov 9, 2023
40dd87f
Merge branch 'master' into gator-sync-support
anlandu Jan 9, 2024
868b144
comments
anlandu Jan 10, 2024
60697ca
comments
anlandu Jan 10, 2024
0fe90b9
fixes
anlandu Jan 11, 2024
8276a17
Merge branch 'master' into gator-sync-support
anlandu Jan 16, 2024
e3571b7
Update website/docs/gator.md
anlandu Jan 17, 2024
db92c4c
Comments
anlandu Jan 17, 2024
8051ead
align with gator expand as that seems to have the most intuitive shor…
anlandu Jan 17, 2024
1dd07e0
Add tempdir flag
anlandu Jan 17, 2024
6c1c9c3
Update pkg/gator/sync/test/test_test.go
anlandu Jan 18, 2024
031b7d6
Merge branch 'master' into gator-sync-support
anlandu Jan 18, 2024
d9af527
f
anlandu Jan 18, 2024
5ae202a
Merge branch 'master' into gator-sync-support
anlandu Apr 5, 2024
52fc3e5
Merge branch 'master' into gator-sync-support
sozercan Apr 23, 2024
bff5fea
gen
anlandu Apr 24, 2024
935b85b
Merge branch 'master' into gator-sync-support
anlandu Apr 25, 2024
6a9eddf
Merge branch 'master' into gator-sync-support
ritazh Jun 25, 2024
a3bb371
Merge branch 'master' into gator-sync-support
anlandu Sep 4, 2024
5e3148d
Merge branch 'master' into gator-sync-support
anlandu Sep 17, 2024
2cfe2aa
fix bad merge
anlandu Sep 17, 2024
bd0c922
Update pkg/gator/reader/read_resources.go
anlandu Sep 17, 2024
8abae8c
Merge branch 'master' into gator-sync-support
ritazh Oct 23, 2024
3854ad2
Merge branch 'master' into gator-sync-support
ritazh Oct 23, 2024
0fb55b5
Merge branch 'master' into gator-sync-support
anlandu Oct 29, 2024
890dc5f
comment
anlandu Oct 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/gator/gator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"os"

"github.com/open-policy-agent/gatekeeper/v3/cmd/gator/expand"
"github.com/open-policy-agent/gatekeeper/v3/cmd/gator/sync"
"github.com/open-policy-agent/gatekeeper/v3/cmd/gator/test"
"github.com/open-policy-agent/gatekeeper/v3/cmd/gator/verify"
"github.com/open-policy-agent/gatekeeper/v3/pkg/version"
Expand All @@ -15,6 +16,7 @@ var commands = []*cobra.Command{
verify.Cmd,
test.Cmd,
expand.Cmd,
sync.Cmd,
k8sVersion.WithFont("alligator2"),
}

Expand Down
28 changes: 28 additions & 0 deletions cmd/gator/sync/sync.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
anlandu marked this conversation as resolved.
Show resolved Hide resolved
*/
package sync

import (
"fmt"

syncverify "github.com/open-policy-agent/gatekeeper/v3/cmd/gator/sync/verify"
"github.com/spf13/cobra"
)

var commands = []*cobra.Command{
syncverify.Cmd,
}

// Cmd represents the sync command.
anlandu marked this conversation as resolved.
Show resolved Hide resolved
var Cmd = &cobra.Command{
Use: "sync",
Short: "Manage SyncSets and Config",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Usage: gator sync create or gator sync verify")
anlandu marked this conversation as resolved.
Show resolved Hide resolved
},
}

func init() {
Cmd.AddCommand(commands...)
}
66 changes: 66 additions & 0 deletions cmd/gator/sync/verify/verify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package verify

import (
"bytes"
"fmt"
"os"

cmdutils "github.com/open-policy-agent/gatekeeper/v3/cmd/gator/util"
"github.com/open-policy-agent/gatekeeper/v3/pkg/gator/reader"
"github.com/open-policy-agent/gatekeeper/v3/pkg/gator/sync/verify"
"github.com/spf13/cobra"
)

// Cmd represents the verify command.
var Cmd = &cobra.Command{
Use: "verify",
Short: "Verify that the provided SyncSet(s) and/or Config contain the GVKs required by the input templates.",
Run: run,
}

var (
flagFilenames []string
flagImages []string
flagDiscoveryResults string
)

const (
flagNameFilename = "filename"
flagNameImage = "image"
flagNameDiscoveryResults = "discovery-results"
)

func init() {
Cmd.Flags().StringArrayVarP(&flagFilenames, flagNameFilename, "f", []string{}, "a file or directory containing Kubernetes resources. Can be specified multiple times.")
Cmd.Flags().StringArrayVarP(&flagImages, flagNameImage, "i", []string{}, "a URL to an OCI image containing policies. Can be specified multiple times.")
Cmd.Flags().StringVarP(&flagDiscoveryResults, flagDiscoveryResults, "d", "", "a json string listing the GVKs supported by the cluster as a nested array of groups, containing supported versions, containing supported kinds.")
anlandu marked this conversation as resolved.
Show resolved Hide resolved
anlandu marked this conversation as resolved.
Show resolved Hide resolved
}

func run(cmd *cobra.Command, args []string) {
unstrucs, err := reader.ReadSources(flagFilenames, flagImages, "")
if err != nil {
cmdutils.ErrFatalf("reading: %v", err)
}
if len(unstrucs) == 0 {
cmdutils.ErrFatalf("no input data identified")
}

anlandu marked this conversation as resolved.
Show resolved Hide resolved
missingRequirements, err := verify.Verify(unstrucs, flagDiscoveryResults)
if err != nil {
cmdutils.ErrFatalf("verifying: %v", err)
}

if len(missingRequirements) > 0 {
cmdutils.ErrFatalf("The following requirements were not met: \n%v", resultsToString(missingRequirements))
}

anlandu marked this conversation as resolved.
Show resolved Hide resolved
os.Exit(0)
}

func resultsToString(results map[string][]int) string {
var buf bytes.Buffer
for template, reqs := range results {
buf.WriteString(fmt.Sprintf("%s: %v\n", template, reqs))
}
return buf.String()
}
10 changes: 10 additions & 0 deletions pkg/gator/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,20 @@ var (
// ErrNotAConstraint indicates the user-indicated file does not contain a
// Constraint.
ErrNotAConstraint = errors.New("not a Constraint")
// ErrNotAConfig indicates the user-indicated file does not contain a
// Config.
ErrNotAConfig = errors.New("not a Config")
// ErrNotASyncSet indicates the user-indicated file does not contain a
// SyncSet.
ErrNotASyncSet = errors.New("not a SyncSet")
// ErrAddingTemplate indicates a problem instantiating a Suite's ConstraintTemplate.
ErrAddingTemplate = errors.New("adding template")
// ErrAddingConstraint indicates a problem instantiating a Suite's Constraint.
ErrAddingConstraint = errors.New("adding constraint")
// ErrAddingSyncSet indicates a problem instantiating a Suite's SyncSet.
ErrAddingSyncSet = errors.New("adding syncset")
// ErrAddingConfig indicates a problem instantiating a Suite's Config.
ErrAddingConfig = errors.New("adding config")
// ErrInvalidSuite indicates a Suite does not define the required fields.
ErrInvalidSuite = errors.New("invalid Suite")
// ErrCreatingClient indicates an error instantiating the Client which compiles
Expand Down
153 changes: 153 additions & 0 deletions pkg/gator/fixtures/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,16 @@ metadata:
name: k8suniqueserviceselector
annotations:
description: Requires Services to have unique selectors within a namespace.
metadata.gatekeeper.sh/requires-sync-data: |
"[
[
{
"groups": [""],
"versions": ["v1"],
"kinds": ["Service"]
}
]
]"
spec:
crd:
spec:
Expand Down Expand Up @@ -368,6 +378,118 @@ spec:
}
`

TemplateReferentialMultEquivSets = `
anlandu marked this conversation as resolved.
Show resolved Hide resolved
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8suniqueingresshost
annotations:
metadata.gatekeeper.sh/title: "Unique Ingress Host"
metadata.gatekeeper.sh/version: 1.0.3
metadata.gatekeeper.sh/requires-sync-data: |
"[
[
{
"groups": ["extensions"],
"versions": ["v1beta1"],
"kinds": ["Ingress"]
},
{
"groups": ["networking.k8s.io"],
"versions": ["v1beta1", "v1"],
"kinds": ["Ingress"]
}
]
]"
description: >-
Requires all Ingress rule hosts to be unique.

Does not handle hostname wildcards:
https://kubernetes.io/docs/concepts/services-networking/ingress/
spec:
anlandu marked this conversation as resolved.
Show resolved Hide resolved
crd:
spec:
names:
kind: K8sUniqueIngressHost
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8suniqueingresshost

identical(obj, review) {
obj.metadata.namespace == review.object.metadata.namespace
obj.metadata.name == review.object.metadata.name
}

violation[{"msg": msg}] {
input.review.kind.kind == "Ingress"
re_match("^(extensions|networking.k8s.io)$", input.review.kind.group)
host := input.review.object.spec.rules[_].host
other := data.inventory.namespace[_][otherapiversion]["Ingress"][name]
re_match("^(extensions|networking.k8s.io)/.+$", otherapiversion)
other.spec.rules[_].host == host
not identical(other, input.review)
msg := sprintf("ingress host conflicts with an existing ingress <%v>", [host])
}
`

TemplateReferentialMultReqs = `
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8suniqueingresshostmultireq
annotations:
metadata.gatekeeper.sh/title: "Unique Ingress Host"
metadata.gatekeeper.sh/version: 1.0.3
metadata.gatekeeper.sh/requires-sync-data: |
anlandu marked this conversation as resolved.
Show resolved Hide resolved
"[
[
{
"groups": ["extensions"],
"versions": ["v1beta1"],
"kinds": ["Ingress"]
}
],
[
{
"groups": ["networking.k8s.io"],
"versions": ["v1beta1", "v1"],
"kinds": ["Ingress"]
}
]
]"
description: >-
Requires all Ingress rule hosts to be unique.

Does not handle hostname wildcards:
https://kubernetes.io/docs/concepts/services-networking/ingress/
spec:
crd:
spec:
names:
kind: K8sUniqueIngressHost
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8suniqueingresshost

identical(obj, review) {
obj.metadata.namespace == review.object.metadata.namespace
obj.metadata.name == review.object.metadata.name
}

violation[{"msg": msg}] {
input.review.kind.kind == "Ingress"
re_match("^(extensions|networking.k8s.io)$", input.review.kind.group)
host := input.review.object.spec.rules[_].host
other := data.inventory.namespace[_][otherapiversion]["Ingress"][name]
re_match("^(extensions|networking.k8s.io)/.+$", otherapiversion)
other.spec.rules[_].host == host
not identical(other, input.review)
msg := sprintf("ingress host conflicts with an existing ingress <%v>", [host])
}
`

ConstraintReferential = `
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sUniqueServiceSelector
Expand Down Expand Up @@ -581,5 +703,36 @@ spec:
kinds:
- apiGroups: ["*"]
kinds: ["*"]
`
SyncSet = `
apiVersion: syncset.gatekeeper.sh/v1alpha1
kind: SyncSet
metadata:
name: syncset
namespace: "gatekeeper-system"
spec:
gvks:
- group: "extensions"
version: "v1beta1"
kind: "Ingress"
- group: "apps"
version: "v1"
kind: "Deployment"
`
Config = `
apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
name: config
namespace: "gatekeeper-system"
spec:
sync:
syncOnly:
- group: ""
version: "v1"
kind: "Service"
- group: "apps"
version: "v1"
kind: "Deployment"
`
)
Loading