Skip to content

Commit

Permalink
Merge c2374ea into b7100b6
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonrichardsmith committed Sep 1, 2018
2 parents b7100b6 + c2374ea commit ad30cf3
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 10 deletions.
90 changes: 81 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@

Sentry is a Webhook Validating Admission Controller that enforces rules cluster wide on objects in Kubernetes prior to admission.

This project is in Beta Release

## Rules

Sentry currently supports the below enforcement rules.

If they are not set in the config.yaml with "enabled" set to true, they will not be enforced.

Each can ignore a set of namespaces.

"type" targets the Kuberentes object type.
Each rule can ignore a set of namespaces.

To enforce different configurations you can launch this admission controller under different names with different configurations.

### Limits

Expand All @@ -42,18 +39,17 @@ limits:

Source insures images are only pulled from allowed sources. This is a very simple string match. This will only check if your image string starts with strings provided in the config. To insure your domain is not read as a subdomain, it is best to end your domain with a "/".

By listing the entire image path with or without tag, you can allow specific images from a repository. So "gcr.io/google_containers/pause-amd64" would only allow the pause container.
By listing the entire image path with or without tag, you can allow specific images from a repository. So "gcr.io/google_containers/pause-amd64" would only allow the pause container. Due to the matching strategy this also means "gcr.io/google_containers/pause-amd64foo" would also pass.

```yaml
source:
type: Pod
enabled: true
ignoredNamespaces:
- "test2"
- "test3"
allowed:
- "thisdomain/isallowed"
- "sois/thisone"
- "this/isallowed"
- "sois/this"
```


Expand Down Expand Up @@ -106,3 +102,79 @@ This create server certs, and makes them available in the deployment. It produce

To see the tests working you can deploy any of the manifests under the test-manifests folder.

To run the e2e tests you can run

```bash
make e2etests
```

## Development

To develop a new module, you can copy over the [example](https://github.com/jasonrichardsmith/sentry/tree/example-and-typos/example) module.

It will need to be added to the [mux/config.go](https://github.com/jasonrichardsmith/sentry/blob/example-and-typos/mux/config.go).

```go

type Config struct {
Limits limits.Config `yaml:"limits"`
Healthz healthz.Config `yaml:"healthz"`
Source source.Config `yaml:"source"`
Tags tags.Config `yaml:"tags"`
Example example.Config `yaml:"example"`
}

func New() *Config {
l := limits.Config{}
h := healthz.Config{}
i := tags.Config{}
s := source.Config{}
e := example.Config{}
return &Config{
Limits: l,
Healthz: h,
Tags: i,
Source: s,
Example: e,
}
}
```

and to the [mux/mux.go](https://github.com/jasonrichardsmith/sentry/blob/example-and-typos/mux/mux.go) NewFromConfig function

```go

if c.Example.Enabled {
log.Info("Example enabled loading")
s, err := c.Example.LoadSentry()
if err != nil {
return sm, err
}
mod := sentryModule{
s,
c.Source.IgnoredNamespaces,
}
log.Info("Ignoring Namespaces ", mod.ignored)
sm.Sentries = append(sm.Sentries, mod)
}
```

Hopefully [config loading will be improved](https://github.com/jasonrichardsmith/sentry/issues/2) in the near future.


You can add e2e tests by adding a folder for your module in test-manifests, and adding manifests named in the following convention.

```
description.expectation.yaml
```

Anything not titled with "pass" as an "expectation" will be expected to fail.

Then make sure your module is enabled in the [manifest.yaml](https://github.com/jasonrichardsmith/sentry/blob/example-and-typos/manifest.yaml).
```yaml

example:
enabled: true
ignoredNamespaces:
- "kube-system"
```
13 changes: 13 additions & 0 deletions example/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package example

import (
"github.com/jasonrichardsmith/sentry/sentry"
)

type Config struct {
sentry.Config `yaml:"-,inline"`
}

func (c *Config) LoadSentry() (sentry.Sentry, error) {
return ExampleSentry{}, nil
}
42 changes: 42 additions & 0 deletions example/example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package example

import "k8s.io/api/admission/v1beta1"

var (
// Uncomment to deserialize
/*
scheme = runtime.NewScheme()
codecs = serializer.NewCodecFactory(scheme)
*/
)

// ExampleSentry satisfies sentry.Sentry interface
type ExampleSentry struct{}

// Type returns the type of object you are checking
func (es ExampleSentry) Type() string {
// Return your type here.
return "Pod"
}

// This is your validating function
func (es ExampleSentry) Admit(receivedAdmissionReview v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {

reviewResponse := v1beta1.AdmissionResponse{}
// This is an en example of how to deserialize an object.
/*
raw := receivedAdmissionReview.Request.Object.Raw
pod := corev1.Pod{}
deserializer := codecs.UniversalDeserializer()
reviewResponse := v1beta1.AdmissionResponse{}
if _, _, err := deserializer.Decode(raw, nil, &pod); err != nil {
log.Error(err)
reviewResponse.Result = &metav1.Status{Message: err.Error()}
return &reviewResponse
}
*/
// Here you would validate your pod
// We are just returning true here.
reviewResponse.Allowed = true
return &reviewResponse
}
30 changes: 30 additions & 0 deletions example/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package example

import (
"testing"

"k8s.io/api/admission/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
)

func TestType(t *testing.T) {
ts := ExampleSentry{}
if ts.Type() != "Pod" {
t.Fatal("Failed type test")
}
}

func TestAdmit(t *testing.T) {
s := ExampleSentry{}
ar := v1beta1.AdmissionReview{
Request: &v1beta1.AdmissionRequest{
Object: runtime.RawExtension{
Raw: make([]byte, 0),
},
},
}
resp := s.Admit(ar)
if !resp.Allowed {
t.Fatal("expected passing review")
}
}
5 changes: 4 additions & 1 deletion manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ data:
- "test2"
- "test4"
source:
type: Pod
enabled: true
ignoredNamespaces:
- "kube-system"
Expand All @@ -116,6 +115,10 @@ data:
- "test3"
allowed:
- "gcr.io"
example:
enabled: true
ignoredNamespaces:
- "kube-system"
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
Expand Down
4 changes: 4 additions & 0 deletions mux/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"flag"
"io/ioutil"

"github.com/jasonrichardsmith/sentry/example"
"github.com/jasonrichardsmith/sentry/healthz"
"github.com/jasonrichardsmith/sentry/limits"
"github.com/jasonrichardsmith/sentry/sentry"
Expand All @@ -25,18 +26,21 @@ type Config struct {
Healthz healthz.Config `yaml:"healthz"`
Source source.Config `yaml:"source"`
Tags tags.Config `yaml:"tags"`
Example example.Config `yaml:"example"`
}

func New() *Config {
l := limits.Config{}
h := healthz.Config{}
i := tags.Config{}
s := source.Config{}
e := example.Config{}
return &Config{
Limits: l,
Healthz: h,
Tags: i,
Source: s,
Example: e,
}
}

Expand Down
13 changes: 13 additions & 0 deletions mux/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ func NewFromConfig(c Config) (SentryMux, error) {
log.Info("Ignoring Namespaces ", mod.ignored)
sm.Sentries = append(sm.Sentries, mod)
}
if c.Example.Enabled {
log.Info("Example enabled loading")
s, err := c.Example.LoadSentry()
if err != nil {
return sm, err
}
mod := sentryModule{
s,
c.Source.IgnoredNamespaces,
}
log.Info("Ignoring Namespaces ", mod.ignored)
sm.Sentries = append(sm.Sentries, mod)
}
return sm, nil
}

Expand Down
17 changes: 17 additions & 0 deletions test-manifests/example/example.pass.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: test3
---
apiVersion: v1
kind: Pod
metadata:
name: pass
namespace: test3
labels:
test: label
spec:
containers:
- name: pause
image: gcr.io/google_containers/pause-amd64:3.0

0 comments on commit ad30cf3

Please sign in to comment.