Skip to content
This repository has been archived by the owner on Oct 14, 2020. It is now read-only.

Commit

Permalink
chore: Create template for OLM bundle (#33)
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Pacak <[email protected]>
  • Loading branch information
danielpacak authored Sep 21, 2020
1 parent d75694d commit fec3474
Show file tree
Hide file tree
Showing 18 changed files with 737 additions and 154 deletions.
213 changes: 213 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# Contributing

These guidelines will help you get started with the Starboard Operator project.

## Prerequisites

1. Install Go

The project requires [Go 1.14][go-download] or later. We also assume that you're familiar with
Go's [GOPATH workspace][go-code] convention, and have the appropriate environment variables set.
2. Get the source code:

```
$ git clone [email protected]:aquasecurity/starboard-operator.git
$ cd starboard-operator
```
3. Access to a dev Kubernetes cluster. We assume that you're using a single-node [KIND][kind] cluster created with the
following command:

```
$ kind create cluster
```

## Deployment

You'll deploy the operator in the `starboard-operator` Namespace and configure it to watch the `starboard-operator`
Namespace. In OLM terms such install mode is called `OwnNamespace` and is suitable for end users who want to install
the operator in the same namespace as supervised workloads.

> The `OwnNamespace` mode is good to get started with a basic development workflow. For other install modes see
> [Operator Multitenancy with OperatorGroups][olm-operator-groups].
### Prerequisites

1. Build Docker images:

```
$ export GOOS=linux
$ make docker-build
```

This will build the `docker.io/aquasec/starboard-operator:dev` as well as `docker.io/aquasec/starboard-scanner-aqua:dev`
images. The second image is only used when you enable the Aqua CSP scanner. By default Trivy is used as vulnerability
scanner by pulling its official image accessible from DockerHub (`docker.io/aquasec/trivy:$TRIVY_VERSION`).
2. Load Docker images into the cluster node:

```
$ kind load docker-image aquasec/starboard-operator:dev
$ kind load docker-image aquasec/starboard-scanner-aqua:dev
```
3. Send the definition of the VulnerabilityReport custom resource to the Kubernetes API:

```
$ kubectl apply -f https://raw.githubusercontent.com/aquasecurity/starboard/master/kube/crd/vulnerabilityreports-crd.yaml
```
4. Send the following Kubernetes objects definitions to the Kubernetes API:

```
$ kubectl apply -f deploy/kubectl/01-starboard-operator.ns.yaml \
-f deploy/kubectl/02-starboard-operator.sa.yaml
-f deploy/kubectl/03-starboard-operator.role.yaml
-f deploy/kubectl/04-starboard-operator.rolebinding.yaml
```

This will create the `starboard-operator` Namespace, and the `starboard-operator` ServiceAccount. Beyond that,
it will create the `starboard-operator` Role and bind it to the `starboard-operator` ServiceAccount in the
`starboard-operator` Namespace via the `starboard-operator` RoleBinding.

### In cluster

1. Create the `starboard-operator` Deployment in the `starboard-operator` namespace to run the operator's container:

```
$ kubectl apply -f deploy/kubectl/05-starboard-operator.deployment.yaml
```

### Out of cluster

1. Run the main method of the operator program:

```
$ go run cmd/operator/main.go
```

### Enable Aqua CSP scanner

1. Create the `starboard-operator` secret in the `starboard-operator` namespace that holds the scanner's configuration:

```
$ kubectl create secret generic starboard-operator \
--namespace starboard-operator \
--from-literal OPERATOR_SCANNER_AQUA_CSP_USERNAME=$AQUA_CONSOLE_USERNAME \
--from-literal OPERATOR_SCANNER_AQUA_CSP_PASSWORD=$AQUA_CONSOLE_PASSWORD \
--from-literal OPERATOR_SCANNER_AQUA_CSP_VERSION=$AQUA_VERSION \
--from-literal OPERATOR_SCANNER_AQUA_CSP_HOST=http://csp-console-svc.aqua:8080
```

## Operator Lifecycle Manager

### Prerequisites

1. Install [Operator Lifecycle Manager][olm] (OLM) and [Operator Marketplace][operator-marketplace]:

```
$ ./deploy/olm/install.sh
```

2. Install [Operator Courier][operator-courier]:

```
$ pip3 install operator-courier
```
3. [Sign up][quay] for a free Quay.io account if you're a new user.

### Build OLM bundle

1. Lint the OLM bundle:

```
$ BUNDLE_SRC_DIR=deploy/olm/bundle
$ operator-courier verify $BUNDLE_SRC_DIR
```
2. Retrieve a Quay.io token:
```
$ QUAY_USERNAME=<your quay.io username>
$ QUAY_PASSWORD=<your quay.io password>
$ QUAY_URL=https://quay.io/cnr/api/v1/users/login
$ QUAY_TOKEN=$(curl -s -H "Content-Type: application/json" -XPOST $QUAY_URL -d \
'{"user":{"username":"'"${QUAY_USERNAME}"'","password": "'"${QUAY_PASSWORD}"'"}}' |
jq -r .token)
```
3. Push the OLM bundle to Quay.io:
```
$ QUAY_NAMESPACE=<quay.io namespace>
$ PACKAGE_NAME=starboard-operator
$ PACKAGE_VERSION=<next package version>
$ operator-courier push "$BUNDLE_SRC_DIR" "$QUAY_NAMESPACE" \
"$PACKAGE_NAME" "$PACKAGE_VERSION" "$QUAY_TOKEN"
```

### Create ClusterServiceVersion

1. Create the OperatorSource resource:

```
QUAY_FULL_NAME=<your quay.io full name>
$ cat << EOF | kubectl apply -f -
apiVersion: operators.coreos.com/v1
kind: OperatorSource
metadata:
name: $QUAY_USERNAME-operators
namespace: marketplace
spec:
type: appregistry
endpoint: https://quay.io/cnr
displayName: "$QUAY_FULL_NAME Quay.io Applications"
publisher: "$QUAY_FULL_NAME"
registryNamespace: "$QUAY_USERNAME"
EOF
```

An OperatorSource resource defines the external data store used to host operator bundles. In this case, you will be
defining an OperatorSource to point to your Quay.io account, which will provide access to its hosted OLM bundles.

2. Create the OperatorGroup resource:

```
$ cat << EOF | kubectl apply -f -
apiVersion: operators.coreos.com/v1alpha2
kind: OperatorGroup
metadata:
name: workloads
namespace: marketplace
spec:
targetNamespaces:
- marketplace
EOF
```

You'll need an OperatorGroup to denote which namespaces the operator should watch. It must exist in the namespace
where you want to deploy the operator.

3. Create the Subscription resource:

```
cat << EOF | kubectl apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: starboard-operator
namespace: marketplace
spec:
channel: alpha
name: starboard-operator
source: $QUAY_NAMESPACE-operators
sourceNamespace: marketplace
EOF
```

A Subscription links the previous steps together by selecting an operator and one of its channels. OLM uses this
information to start the corresponding operator Pod. The example above creates a new Subscription to the `alpha`
channel for the Starboard Operator.

[go-download]: https://golang.org/dl/
[go-code]: https://golang.org/doc/code.html
[kind]: https://github.com/kubernetes-sigs/kind
[olm]: https://github.com/operator-framework/operator-lifecycle-manager
[operator-marketplace]: https://github.com/operator-framework/operator-marketplace
[operator-courier]: https://github.com/operator-framework/operator-courier
[olm-operator-groups]: https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/operatorgroups.md
[quay]: https://quay.io
35 changes: 7 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,19 @@ This operator for Starboard automatically updates security report resources in r
a Kubernetes cluster - for example, initiating a vulnerability scan when a new pod is started. Please see the main
[Starboard][starboard] repo for more info about the Starboard project.

## Getting started
## Contributing

1. Run `make` to build operator binaries into Docker containers:
```
$ make docker-build
```
1. Define Custom Security Resources used by Starboard:
```
$ kubectl apply -f https://raw.githubusercontent.com/aquasecurity/starboard/master/kube/crd/vulnerabilityreports-crd.yaml
```
2. Create the `starboard-operator` Namespace:
```
$ kubectl create ns starboard-operator
```
3. Create a Secret that holds configuration of the Aqua CSP scanner:
```
$ kubectl create secret generic starboard-operator \
--namespace starboard-operator \
--from-literal OPERATOR_SCANNER_AQUA_CSP_USERNAME=$AQUA_CONSOLE_USERNAME \
--from-literal OPERATOR_SCANNER_AQUA_CSP_PASSWORD=$AQUA_CONSOLE_PASSWORD \
--from-literal OPERATOR_SCANNER_AQUA_CSP_VERSION=$AQUA_VERSION \
--from-literal OPERATOR_SCANNER_AQUA_CSP_HOST=http://csp-console-svc.aqua:8080
```
5. Create a Deployment for the Starboard Operator:
```
$ kubectl apply -f deploy/starboard-operator.yaml
```
Thanks for taking the time to join our community and start contributing!

- See [CONTRIBUTING.md](CONTRIBUTING.md) for information about setting up your development environment and deploying the operator.
- Check out the [open issues](https://github.com/aquasecurity/starboard-operator/issues).

## Configuration

| Name | Default | Description |
|-----------------------------------------|----------------------|-------------|
| `OPERATOR_NAMESPACE` | `` | The namespace the operator is running in. |
| `OPERATOR_TARGET_NAMESPACE` | `` | The namespace the operator should be watching for changes. This can be a comma separated list of names to watch multiple namespaces (e.g. `ns1,ns2`). |
| `OPERATOR_NAMESPACE` | N/A | The namespace the operator is running in. |
| `OPERATOR_TARGET_NAMESPACES` | N/A | The namespace the operator should be watching for changes. This can be a comma separated list of names to watch multiple namespaces (e.g. `ns1,ns2`). |
| `OPERATOR_SCAN_JOB_TIMEOUT` | `5m` | The length of time to wait before giving up on a scan job |
| `OPERATOR_SCANNER_TRIVY_ENABLED` | `true` | The flag to enable Trivy vulnerability scanner |
| `OPERATOR_SCANNER_TRIVY_VERSION` | `0.11.0` | The version of Trivy to be used |
Expand Down
15 changes: 8 additions & 7 deletions cmd/operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,18 @@ func run() error {
Scheme: scheme,
}

if len(targetNamespaces) == 1 {
// Add support for OwnNamespace and SingleNamespace set in STARBOARD_TARGET_NAMESPACE (e.g. ns1).
if len(targetNamespaces) == 1 && targetNamespaces[0] == operatorNamespace {
// Add support for OwnNamespace set in STARBOARD_TARGET_NAMESPACES (e.g. ns1).
setupLog.Info("Constructing single-namespaced cache", "namespace", targetNamespaces[0])
options.Namespace = targetNamespaces[0]
} else {
// Add support for MultiNamespace set in STARBOARD_TARGET_NAMESPACE (e.g. ns1,ns2).
// Add support for SingleNamespace and MultiNamespace set in STARBOARD_TARGET_NAMESPACES (e.g. ns1,ns2).
// Note that we may face performance issues when using this with a high number of namespaces.
// More: https://godoc.org/github.com/kubernetes-sigs/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder
setupLog.Info("Constructing multi-namespaced cache", "namespaces", targetNamespaces)
cachedNamespaces := append(targetNamespaces, operatorNamespace)
setupLog.Info("Constructing multi-namespaced cache", "namespaces", cachedNamespaces)
options.Namespace = ""
options.NewCache = cache.MultiNamespacedCacheBuilder(targetNamespaces)
options.NewCache = cache.MultiNamespacedCacheBuilder(cachedNamespaces)
}

kubernetesConfig, err := ctrl.GetConfig()
Expand Down Expand Up @@ -141,7 +142,7 @@ func run() error {
Client: mgr.GetClient(),
Store: store,
Scanner: scanner,
Log: ctrl.Log.WithName("controller").WithName("pods"),
Log: ctrl.Log.WithName("controller").WithName("Pod"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
return fmt.Errorf("unable to create pod controller: %w", err)
Expand All @@ -153,7 +154,7 @@ func run() error {
Client: mgr.GetClient(),
Store: store,
Scanner: scanner,
Log: ctrl.Log.WithName("controller").WithName("scan-jobs"),
Log: ctrl.Log.WithName("controller").WithName("Job"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
return fmt.Errorf("unable to create job controller: %w", err)
Expand Down
2 changes: 1 addition & 1 deletion deploy/examples/aqua-scan-job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ spec:
mountPath: /downloads
containers:
- name: scanner
image: docker.io/aquasec/starboard-scanner-aqua:0.0.1-alpha.2
image: docker.io/aquasec/starboard-scanner-aqua:0.0.1-alpha.4
imagePullPolicy: IfNotPresent
command:
- "/bin/sh"
Expand Down
5 changes: 5 additions & 0 deletions deploy/kubectl/01-starboard-operator.ns.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: starboard-operator
6 changes: 6 additions & 0 deletions deploy/kubectl/02-starboard-operator.sa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: starboard-operator
namespace: starboard-operator
43 changes: 43 additions & 0 deletions deploy/kubectl/03-starboard-operator.role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: starboard-operator
namespace: starboard-operator
rules:
- apiGroups:
- ""
resources:
- "pods"
- "pods/log"
verbs:
- get
- list
- watch
- apiGroups:
- apps
resources:
- replicasets
verbs:
- get
- list
- watch
- apiGroups:
- batch
resources:
- jobs
verbs:
- get
- list
- watch
- create
- delete
- apiGroups:
- aquasecurity.github.io
resources:
- vulnerabilityreports
verbs:
- get
- list
- watch
- create
14 changes: 14 additions & 0 deletions deploy/kubectl/04-starboard-operator.rolebinding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: starboard-operator
namespace: starboard-operator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: starboard-operator
subjects:
- kind: ServiceAccount
name: starboard-operator
namespace: starboard-operator
Loading

0 comments on commit fec3474

Please sign in to comment.