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: Ensure default config should not create ConfigMap for Polaris when it is not chosen as plugin #530

Merged
merged 1 commit into from
Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 0 additions & 6 deletions deploy/static/05-starboard-operator.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,3 @@ kind: Secret
metadata:
name: starboard
namespace: starboard-operator
---
apiVersion: v1
kind: ConfigMap
metadata:
name: starboard-conftest-config
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static YAMLs hardcode config audit plugin to Polaris so we won't create ConfigMap for Conftest

namespace: starboard-operator
70 changes: 48 additions & 22 deletions pkg/starboard/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,17 @@ func GetDefaultConfig() ConfigData {
}

// GetDefaultPolarisConfig returns the default Polaris configuration.
func GetDefaultPolarisConfig() ConfigData {
func GetDefaultPolarisConfig() map[string]string {
return map[string]string{
"polaris.config.yaml": polarisConfigYAML,
}
}

// GetDefaultConftestConfig return the defautl Conftest configuration.
func GetDefaultConftestConfig() map[string]string {
return map[string]string{}
}

func (c ConfigData) GetVulnerabilityReportsScanner() (Scanner, error) {
var ok bool
var value string
Expand Down Expand Up @@ -424,49 +429,70 @@ type configManager struct {
}

func (c *configManager) EnsureDefault(ctx context.Context) error {
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: c.namespace,
Name: ConfigMapName,
Labels: labels.Set{
"app.kubernetes.io/managed-by": "starboard",
cm, err := c.client.CoreV1().ConfigMaps(c.namespace).Get(ctx, ConfigMapName, metav1.GetOptions{})
if err != nil {
if !apierrors.IsNotFound(err) {
return fmt.Errorf("getting config: %w", err)
}

cm, err = c.client.CoreV1().ConfigMaps(c.namespace).Create(ctx, &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: c.namespace,
Name: ConfigMapName,
Labels: labels.Set{
LabelK8SAppManagedBy: "starboard",
},
},
},
Data: GetDefaultConfig(),
}
_, err := c.client.CoreV1().ConfigMaps(c.namespace).Create(ctx, cm, metav1.CreateOptions{})
if err != nil && !apierrors.IsAlreadyExists(err) {
return err
Data: GetDefaultConfig(),
}, metav1.CreateOptions{})

if err != nil {
return fmt.Errorf("creating config: %w", err)
}
}

polarisCm := &corev1.ConfigMap{
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: c.namespace,
Name: GetPluginConfigMapName(string(Polaris)),
Name: SecretName,
Labels: labels.Set{
"app.kubernetes.io/managed-by": "starboard",
LabelK8SAppManagedBy: "starboard",
},
},
Data: GetDefaultPolarisConfig(),
}
_, err = c.client.CoreV1().ConfigMaps(c.namespace).Create(ctx, polarisCm, metav1.CreateOptions{})
_, err = c.client.CoreV1().Secrets(c.namespace).Create(ctx, secret, metav1.CreateOptions{})
if err != nil && !apierrors.IsAlreadyExists(err) {
return err
}

secret := &corev1.Secret{
scanner, err := ConfigData(cm.Data).GetConfigAuditReportsScanner()
if err != nil {
return fmt.Errorf("getting scanner: %w", err)
}

var pluginConfigData map[string]string
switch scanner {
case Polaris:
pluginConfigData = GetDefaultPolarisConfig()
case Conftest:
pluginConfigData = GetDefaultConftestConfig()
}

pluginConfig := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: c.namespace,
Name: SecretName,
Name: GetPluginConfigMapName(string(scanner)),
Labels: labels.Set{
"app.kubernetes.io/managed-by": "starboard",
LabelK8SAppManagedBy: "starboard",
},
},
Data: pluginConfigData,
}
_, err = c.client.CoreV1().Secrets(c.namespace).Create(ctx, secret, metav1.CreateOptions{})
_, err = c.client.CoreV1().ConfigMaps(c.namespace).Create(ctx, pluginConfig, metav1.CreateOptions{})
if err != nil && !apierrors.IsAlreadyExists(err) {
return err
}

return nil
}

Expand Down
194 changes: 166 additions & 28 deletions pkg/starboard/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"github.com/aquasecurity/starboard/pkg/starboard"
"github.com/onsi/gomega"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -324,67 +325,204 @@ func TestConfigManager_Read(t *testing.T) {

func TestConfigManager_EnsureDefault(t *testing.T) {

t.Run("Should create ConfigMap with default values, and empty secret", func(t *testing.T) {
t.Run("Should create ConfigMaps and Secret", func(t *testing.T) {
g := gomega.NewGomegaWithT(t)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gomega is more flexible and expressive than testify. We also use Gomega in integration tests so I'd like to stick to Gomega for new code.


namespace := "starboard-ns"
clientset := fake.NewSimpleClientset()

err := starboard.NewConfigManager(clientset, starboard.NamespaceName).EnsureDefault(context.TODO())
require.NoError(t, err)
err := starboard.NewConfigManager(clientset, namespace).EnsureDefault(context.TODO())
g.Expect(err).ToNot(gomega.HaveOccurred())

cm, err := clientset.CoreV1().
ConfigMaps(starboard.NamespaceName).
cm, err := clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.ConfigMapName, metav1.GetOptions{})
require.NoError(t, err)
assert.Equal(t, starboard.GetDefaultConfig(), starboard.ConfigData(cm.Data))
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(cm.Data).To(gomega.BeEquivalentTo(starboard.GetDefaultConfig()))

secret, err := clientset.CoreV1().
Secrets(starboard.NamespaceName).
secret, err := clientset.CoreV1().Secrets(namespace).
Get(context.TODO(), starboard.SecretName, metav1.GetOptions{})
require.NoError(t, err)
assert.Equal(t, map[string][]byte(nil), secret.Data)
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(secret.Data).To(gomega.BeEmpty())

pluginConfig, err := clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.GetPluginConfigMapName(string(starboard.Polaris)), metav1.GetOptions{})
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(pluginConfig.Data).To(gomega.Equal(starboard.GetDefaultPolarisConfig()))

_, err = clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.GetPluginConfigMapName(string(starboard.Conftest)), metav1.GetOptions{})
g.Expect(err).To(gomega.MatchError(`configmaps "starboard-conftest-config" not found`))
})

t.Run("Should not modify ConfigMap nor secret if they already exist", func(t *testing.T) {
t.Run("Should not modify ConfigMaps nor Secret", func(t *testing.T) {
g := gomega.NewGomegaWithT(t)
namespace := "starboard-ns"
clientset := fake.NewSimpleClientset(
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: starboard.NamespaceName,
Namespace: namespace,
Name: starboard.ConfigMapName,
},
Data: map[string]string{
"foo": "bar",
"foo": "bar",
"configAuditReports.scanner": string(starboard.Conftest),
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: starboard.NamespaceName,
Namespace: namespace,
Name: starboard.SecretName,
},
Data: map[string][]byte{
"baz": []byte("s3cret"),
},
},
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: starboard.GetPluginConfigMapName(string(starboard.Conftest)),
},
Data: map[string]string{
"conftest.policy.my-check.rego": "<REGO>",
},
},
)

err := starboard.NewConfigManager(clientset, starboard.NamespaceName).EnsureDefault(context.TODO())
require.NoError(t, err)
err := starboard.NewConfigManager(clientset, namespace).EnsureDefault(context.TODO())
g.Expect(err).ToNot(gomega.HaveOccurred())

cm, err := clientset.CoreV1().
ConfigMaps(starboard.NamespaceName).
cm, err := clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.ConfigMapName, metav1.GetOptions{})
require.NoError(t, err)
assert.Equal(t, map[string]string{
"foo": "bar",
}, cm.Data)
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(cm.Data).To(gomega.Equal(map[string]string{
"foo": "bar",
"configAuditReports.scanner": "Conftest",
}))

secret, err := clientset.CoreV1().
Secrets(starboard.NamespaceName).
secret, err := clientset.CoreV1().Secrets(namespace).
Get(context.TODO(), starboard.SecretName, metav1.GetOptions{})
require.NoError(t, err)
assert.Equal(t, map[string][]byte{
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(secret.Data).To(gomega.Equal(map[string][]byte{
"baz": []byte("s3cret"),
}, secret.Data)
}))

pluginConfig, err := clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.GetPluginConfigMapName(string(starboard.Conftest)), metav1.GetOptions{})
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(pluginConfig.Data).To(gomega.Equal(map[string]string{
"conftest.policy.my-check.rego": "<REGO>",
}))

_, err = clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.GetPluginConfigMapName(string(starboard.Polaris)), metav1.GetOptions{})
g.Expect(err).To(gomega.MatchError(`configmaps "starboard-polaris-config" not found`))
})

t.Run("Should create ConfigMap for Polaris", func(t *testing.T) {
g := gomega.NewGomegaWithT(t)
namespace := "starboard-ns"
clientset := fake.NewSimpleClientset(
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: starboard.ConfigMapName,
},
Data: map[string]string{
"foo": "bar",
"configAuditReports.scanner": string(starboard.Polaris),
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: starboard.SecretName,
},
Data: map[string][]byte{
"baz": []byte("s3cret"),
},
},
)

err := starboard.NewConfigManager(clientset, namespace).EnsureDefault(context.TODO())
g.Expect(err).ToNot(gomega.HaveOccurred())

cm, err := clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.ConfigMapName, metav1.GetOptions{})
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(cm.Data).To(gomega.Equal(map[string]string{
"foo": "bar",
"configAuditReports.scanner": "Polaris",
}))

secret, err := clientset.CoreV1().Secrets(namespace).
Get(context.TODO(), starboard.SecretName, metav1.GetOptions{})
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(secret.Data).To(gomega.Equal(map[string][]byte{
"baz": []byte("s3cret"),
}))

pluginConfig, err := clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.GetPluginConfigMapName(string(starboard.Polaris)), metav1.GetOptions{})
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(pluginConfig.Data).To(gomega.Equal(starboard.GetDefaultPolarisConfig()))

_, err = clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.GetPluginConfigMapName(string(starboard.Conftest)), metav1.GetOptions{})
g.Expect(err).To(gomega.MatchError(`configmaps "starboard-conftest-config" not found`))
})

t.Run("Should create ConfigMap for Conftest", func(t *testing.T) {
g := gomega.NewGomegaWithT(t)
namespace := "starboard-ns"
clientset := fake.NewSimpleClientset(
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: starboard.ConfigMapName,
},
Data: map[string]string{
"foo": "bar",
"configAuditReports.scanner": string(starboard.Conftest),
},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: starboard.SecretName,
},
Data: map[string][]byte{
"baz": []byte("s3cret"),
},
},
)

err := starboard.NewConfigManager(clientset, namespace).EnsureDefault(context.TODO())
g.Expect(err).ToNot(gomega.HaveOccurred())

cm, err := clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.ConfigMapName, metav1.GetOptions{})
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(cm.Data).To(gomega.Equal(map[string]string{
"foo": "bar",
"configAuditReports.scanner": "Conftest",
}))

secret, err := clientset.CoreV1().Secrets(namespace).
Get(context.TODO(), starboard.SecretName, metav1.GetOptions{})
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(secret.Data).To(gomega.Equal(map[string][]byte{
"baz": []byte("s3cret"),
}))

pluginConfig, err := clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.GetPluginConfigMapName(string(starboard.Conftest)), metav1.GetOptions{})
g.Expect(err).ToNot(gomega.HaveOccurred())
g.Expect(pluginConfig.Data).To(gomega.BeEmpty())

_, err = clientset.CoreV1().ConfigMaps(namespace).
Get(context.TODO(), starboard.GetPluginConfigMapName(string(starboard.Polaris)), metav1.GetOptions{})
g.Expect(err).To(gomega.MatchError(`configmaps "starboard-polaris-config" not found`))
})
}

func TestConfigManager_Delete(t *testing.T) {
Expand Down