cyberark/secretless-broker

View on GitHub
resource-definitions/README.md

Summary

Maintainability
Test Coverage
# Secretless Broker Custom Resource Definitions (CRDs)

This folder contains most of the resources for dealing with CRDs in the context of
this codebase. CRDs are planned to be used for dynamically updating the broker
configuration across the cluster when the API is changed.

For more information about CRDs, you can find more information
[here](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)

# Pre-requisites

In order to work with this module, as well as if you are using the `crd_watcher`
and `crd_injector`, you will need to be sure you have installed the
[development prerequisites](../CONTRIBUTING.md#prerequisites).

# Examples

To manually create the CRD, let's first ensure that we have none already defined:
```
$ kubectl get crd
No resources found.
```

Now lets apply our CRD file template:
```
$ kubectl apply -f ./secretless-resource-definition.yaml
customresourcedefinition.apiextensions.k8s.io "configurations.secretless.io" created
```

Let's take a look at what we have:
```
$ kubectl get crd
NAME                           AGE
configurations.secretless.io   1m

$ kubectl get crd -o yaml
apiVersion: v1
items:
- apiVersion: apiextensions.k8s.io/v1
  kind: CustomResourceDefinition
  metadata:
    annotations:
      ...
    creationTimestamp: 2018-08-17T15:39:40Z
    generation: 1
    name: configurations.secretless.io
...

```

Let us now add some configuration data:
```
$ kubectl apply -f ./sbconfig-example.yaml
configuration.secretless.io "secretless-example-config" created
```

We can now list and display our configuration:
```
$ kubectl get sbconfig
NAME                        AGE
secretless-example-config   1m

$ kubectl describe sbconfig secretless-example-config
Name:         secretless-example-config
Namespace:    default
...

```

The charm of CRDs is also that we can have multiple CRD resources so that
we can apply multiple configurations to our cluster:
```
$ kubectl apply -f ./sbconfig-example2-v1.yaml
configuration.secretless.io "secretless-example-config2" created

$ kubectl get sbconfig
NAME                         AGE
secretless-example-config    22s
secretless-example-config2   17s

$ kubectl describe sbconfig secretless-example-config2
Name:         secretless-example-config2
...
Spec:
  Handlers:
    Credentials:
      Id:        user1
      Name:      username
      Provider:  literal
      Id:        password1
      Name:      password
      Provider:  literal
    Listener:    http_config_1_listener
    Match:
      ^http.*
    Name:  http_config_1_handler
    Type:  basic_auth
  Listeners:
    Address:   0.0.0.0:8080
    Name:      http_config_1_listener
    Protocol:  http
```

Let's try updating only this config with a new one:
```
$ kubectl apply -f ./sbconfig-example2-v2.yaml
configuration.secretless.io "secretless-example-config2" configured

$ kubectl describe sbconfig secretless-example-config2
Name:         secretless-example-config2
...
Spec:
  Handlers:
    Credentials:
      Id:        user2
      Name:      username
      Provider:  literal
      Id:        password2
      Name:      password
      Provider:  literal
    Listener:    http_config_1_listener
    Match:
      ^http.*
    Name:  http_config_1_handler
    Type:  basic_auth
  Listeners:
    Address:   0.0.0.0:9090
    Name:      http_config_1_listener
    Protocol:  http
```

Now that we are done, we can clean up both our configurations and the CRD:
```
$ kubectl delete sbconfig secretless-example-config
configuration.secretless.io "secretless-example-config" deleted

$ kubectl delete sbconfig secretless-example-config2
configuration.secretless.io "secretless-example-config2" deleted

$ kubectl delete crd configurations.secretless.io
customresourcedefinition.apiextensions.k8s.io "configurations.secretless.io" deleted
```

# Adding CRD through code

This method is a bit more complicated, especially if it's run in-cluster due to needing to
have service account privileges but with that prerequisite, you can then use the `crd_injector.go`:

Open the `crd_injector.go` file in an editor and add the CRD schema:

```go
var crdSchema = &apiextensionsv1.JSONSchemaProps{
 // NOTE: Take the CRD schema from the internal/configurationmanagers/kubernetes/crd/crd_injector.go
}
```

```
$ kubectl get crd
No resources found.

$ go run ./crd_injector.go
2018/08/17 10:55:35 Secretless CRD injector starting up...
2018/08/17 10:55:35 Using home dir config...
2018/08/17 10:55:35 Creating K8s client...
2018/08/17 10:55:35 Creating CRD...
2018/08/17 10:55:35 CRD was uccessfully added!
2018/08/17 10:55:35 Done!

$ kubectl get crd
NAME                           AGE
configurations.secretless.io   5s
```

# Watching CRD changes from code

This code requires you to have a service account privileges but with those,
you can use the `crd_watcher.go`:

In one terminal start the watcher after you have added a CRD definition:
```
$ go run ./crd_watcher.go
2018/08/21 16:05:46 Secretless CRD watcher starting up...
2018/08/21 16:05:46 Using home dir config...
2018/08/21 16:05:46 Available configs: 0
2018/08/21 16:05:46 Watching for changes...
```

Open another terminal and add a CRD definition:
```
$ kubectl apply -f ./sbconfig-example.yaml
configuration.secretless.io "secretless-example-config" created
```

Observe that the watcher has noticed the change:
```
2018/08/21 16:05:46 Watching for changes...
metadata:
  name: secretless-example-config
  generatename: ""
  namespace: default
  selflink: /apis/secretless.io/v1/namespaces/default/configurations/secretless-example-config
  ...
spec:
  listeners:
  ...
  handlers:
  ...
```

We can also add the second definion and swap the versions a few times:
```
$ kubectl apply -f sbconfig-example2-v1.yaml
configuration.secretless.io "secretless-example-config2" created

$ kubectl apply -f sbconfig-example2-v2.yaml
configuration.secretless.io "secretless-example-config2" configured

$ kubectl apply -f sbconfig-example2-v1.yaml
configuration.secretless.io "secretless-example-config2" configured
```

You should notice that we see changes in the output of the watcher:
```
2018/08/28 10:17:09 Add
2018/08/28 10:17:09 Add event:
metadata:
  name: secretless-example-config2
...
spec:
  listeners:
  - address: 0.0.0.0:8080
    name: http_config_1_listener
...

2018/08/28 10:17:15 Update
2018/08/28 10:17:15 Update event:
2018/08/28 10:17:15 Old:
metadata:
  name: secretless-example-config2
...
spec:
  listeners:
  - address: 0.0.0.0:9090
    name: http_config_1_listen
...

2018/08/28 10:17:13 Update
2018/08/28 10:17:13 Update event:
2018/08/28 10:17:13 Old:
metadata:
  name: secretless-example-config2
...
spec:
  listeners:
  - address: 0.0.0.0:8080
    name: http_config_1_listener
...
```

After you are done, don't forget to clean up your CRDs:
```
$ kubectl delete sbconfig secretless-example-config
configuration.secretless.io "secretless-example-config" deleted

$ kubectl delete sbconfig secretless-example-config2
configuration.secretless.io "secretless-example-config2" deleted

$ kubectl delete crd configurations.secretless.io
customresourcedefinition.apiextensions.k8s.io "configurations.secretless.io" deleted
```