diff --git a/README.adoc b/README.adoc index d428de142..12ac76c85 100644 --- a/README.adoc +++ b/README.adoc @@ -514,6 +514,10 @@ The types of configuration supported include: * link:https://kubernetes.io/docs/concepts/storage/volumes/[volumes] and volume mounts +* link:https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/[serviceAccount] to run each component with separate identity + +* link:https://kubernetes.io/docs/tasks/configure-pod-container/security-context/[securityContext] to define privileges of running components + [source,yaml] ---- apiVersion: jaegertracing.io/v1 @@ -563,6 +567,9 @@ spec: operator: "Equal" value: "value1" effect: "NoExecute" + serviceAccount: nameOfServiceAccount + securityContext: + runAsUser: 1000 volumeMounts: - name: config-vol mountPath: /etc/config diff --git a/pkg/account/const.go b/pkg/account/const.go new file mode 100644 index 000000000..ee5ce2f41 --- /dev/null +++ b/pkg/account/const.go @@ -0,0 +1,21 @@ +package account + +// Component represents type of jaeger component +type Component string + +const ( + // CollectorComponent represents the value for the Component type for Jaeger Collector + CollectorComponent Component = "collector" + + // QueryComponent represents the value for the Component type for Jaeger Query + QueryComponent Component = "query" + + // IngesterComponent represents the value for the Component type for Jaeger Ingester + IngesterComponent Component = "ingester" + + // AllInOneComponent represents the value for the Component type for Jaeger All-In-One + AllInOneComponent Component = "all-in-one" + + // AgentComponent epresents the value for the Component type for Jaeger Agent + AgentComponent Component = "agent" +) diff --git a/pkg/account/main.go b/pkg/account/main.go index 56ce59140..810309c59 100644 --- a/pkg/account/main.go +++ b/pkg/account/main.go @@ -1,12 +1,11 @@ package account import ( - "fmt" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/jaegertracing/jaeger-operator/pkg/apis/jaegertracing/v1" + "github.com/jaegertracing/jaeger-operator/pkg/util" ) // Get returns all the service accounts to be created for this Jaeger instance @@ -22,11 +21,11 @@ func getMain(jaeger *v1.Jaeger) *corev1.ServiceAccount { trueVar := true return &corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ - Name: JaegerServiceAccountFor(jaeger), + Name: JaegerServiceAccountFor(jaeger, ""), Namespace: jaeger.Namespace, Labels: map[string]string{ "app": "jaeger", - "app.kubernetes.io/name": JaegerServiceAccountFor(jaeger), + "app.kubernetes.io/name": JaegerServiceAccountFor(jaeger, ""), "app.kubernetes.io/instance": jaeger.Name, "app.kubernetes.io/component": "service-account", "app.kubernetes.io/part-of": "jaeger", @@ -46,6 +45,23 @@ func getMain(jaeger *v1.Jaeger) *corev1.ServiceAccount { } // JaegerServiceAccountFor prints service name for Jaeger instance -func JaegerServiceAccountFor(jaeger *v1.Jaeger) string { - return fmt.Sprintf("%s", jaeger.Name) +func JaegerServiceAccountFor(jaeger *v1.Jaeger, component Component) string { + sa := "" + switch component { + case CollectorComponent: + sa = util.Merge([]v1.JaegerCommonSpec{jaeger.Spec.Collector.JaegerCommonSpec, jaeger.Spec.JaegerCommonSpec}).ServiceAccount + case QueryComponent: + sa = util.Merge([]v1.JaegerCommonSpec{jaeger.Spec.Query.JaegerCommonSpec, jaeger.Spec.JaegerCommonSpec}).ServiceAccount + case IngesterComponent: + sa = util.Merge([]v1.JaegerCommonSpec{jaeger.Spec.Ingester.JaegerCommonSpec, jaeger.Spec.JaegerCommonSpec}).ServiceAccount + case AllInOneComponent: + sa = util.Merge([]v1.JaegerCommonSpec{jaeger.Spec.AllInOne.JaegerCommonSpec, jaeger.Spec.JaegerCommonSpec}).ServiceAccount + case AgentComponent: + sa = util.Merge([]v1.JaegerCommonSpec{jaeger.Spec.Agent.JaegerCommonSpec, jaeger.Spec.JaegerCommonSpec}).ServiceAccount + } + + if sa == "" { + return jaeger.Name + } + return sa } diff --git a/pkg/account/main_test.go b/pkg/account/main_test.go index 5300f9fe5..488ceb57d 100644 --- a/pkg/account/main_test.go +++ b/pkg/account/main_test.go @@ -33,5 +33,16 @@ func TestWithSecurityOAuthProxy(t *testing.T) { func TestJaegerName(t *testing.T) { jaeger := v1.NewJaeger("foo") - assert.Equal(t, "foo", JaegerServiceAccountFor(jaeger)) + jaeger.Spec.ServiceAccount = "bar" + jaeger.Spec.Collector.ServiceAccount = "col-sa" + jaeger.Spec.Query.ServiceAccount = "query-sa" + jaeger.Spec.Agent.ServiceAccount = "agent-sa" + jaeger.Spec.AllInOne.ServiceAccount = "aio-sa" + + assert.Equal(t, "foo", JaegerServiceAccountFor(jaeger, "")) + assert.Equal(t, "col-sa", JaegerServiceAccountFor(jaeger, CollectorComponent)) + assert.Equal(t, "query-sa", JaegerServiceAccountFor(jaeger, QueryComponent)) + assert.Equal(t, "aio-sa", JaegerServiceAccountFor(jaeger, AllInOneComponent)) + assert.Equal(t, "agent-sa", JaegerServiceAccountFor(jaeger, AgentComponent)) + assert.Equal(t, "bar", JaegerServiceAccountFor(jaeger, IngesterComponent)) } diff --git a/pkg/apis/jaegertracing/v1/jaeger_types.go b/pkg/apis/jaegertracing/v1/jaeger_types.go index da1e594f2..bdfa91165 100644 --- a/pkg/apis/jaegertracing/v1/jaeger_types.go +++ b/pkg/apis/jaegertracing/v1/jaeger_types.go @@ -86,13 +86,15 @@ type Jaeger struct { // JaegerCommonSpec defines the common elements used in multiple other spec structs // +k8s:openapi-gen=true type JaegerCommonSpec struct { - Volumes []v1.Volume `json:"volumes"` - VolumeMounts []v1.VolumeMount `json:"volumeMounts"` - Annotations map[string]string `json:"annotations,omitempty"` - Labels map[string]string `json:"labels,omitempty"` - Resources v1.ResourceRequirements `json:"resources,omitempty"` - Affinity *v1.Affinity `json:"affinity,omitempty"` - Tolerations []v1.Toleration `json:"tolerations,omitempty"` + Volumes []v1.Volume `json:"volumes"` + VolumeMounts []v1.VolumeMount `json:"volumeMounts"` + Annotations map[string]string `json:"annotations,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Resources v1.ResourceRequirements `json:"resources,omitempty"` + Affinity *v1.Affinity `json:"affinity,omitempty"` + Tolerations []v1.Toleration `json:"tolerations,omitempty"` + SecurityContext *v1.PodSecurityContext `json:"securityContext,omitempty"` + ServiceAccount string `json:"serviceAccount,omitempty"` } // JaegerQuerySpec defines the options to be used when deploying the query diff --git a/pkg/apis/jaegertracing/v1/zz_generated.deepcopy.go b/pkg/apis/jaegertracing/v1/zz_generated.deepcopy.go index 9173656f9..3de02d2c4 100644 --- a/pkg/apis/jaegertracing/v1/zz_generated.deepcopy.go +++ b/pkg/apis/jaegertracing/v1/zz_generated.deepcopy.go @@ -207,6 +207,11 @@ func (in *JaegerCommonSpec) DeepCopyInto(out *JaegerCommonSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.SecurityContext != nil { + in, out := &in.SecurityContext, &out.SecurityContext + *out = new(corev1.PodSecurityContext) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/deployment/agent.go b/pkg/deployment/agent.go index 3fb34ce44..aa3a33fe5 100644 --- a/pkg/deployment/agent.go +++ b/pkg/deployment/agent.go @@ -12,6 +12,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "github.com/jaegertracing/jaeger-operator/pkg/account" "github.com/jaegertracing/jaeger-operator/pkg/apis/jaegertracing/v1" "github.com/jaegertracing/jaeger-operator/pkg/service" "github.com/jaegertracing/jaeger-operator/pkg/util" @@ -147,8 +148,10 @@ func (a *Agent) Get() *appsv1.DaemonSet { }, Resources: commonSpec.Resources, }}, - Affinity: commonSpec.Affinity, - Tolerations: commonSpec.Tolerations, + Affinity: commonSpec.Affinity, + Tolerations: commonSpec.Tolerations, + SecurityContext: commonSpec.SecurityContext, + ServiceAccountName: account.JaegerServiceAccountFor(a.jaeger, account.AgentComponent), }, }, }, diff --git a/pkg/deployment/all-in-one.go b/pkg/deployment/all-in-one.go index 9ab21a59f..bce0f0af6 100644 --- a/pkg/deployment/all-in-one.go +++ b/pkg/deployment/all-in-one.go @@ -175,9 +175,10 @@ func (a *AllInOne) Get() *appsv1.Deployment { Resources: commonSpec.Resources, }}, Volumes: commonSpec.Volumes, - ServiceAccountName: account.JaegerServiceAccountFor(a.jaeger), + ServiceAccountName: account.JaegerServiceAccountFor(a.jaeger, account.AllInOneComponent), Affinity: commonSpec.Affinity, Tolerations: commonSpec.Tolerations, + SecurityContext: commonSpec.SecurityContext, }, }, }, diff --git a/pkg/deployment/collector.go b/pkg/deployment/collector.go index 165c7c104..c93d40fe2 100644 --- a/pkg/deployment/collector.go +++ b/pkg/deployment/collector.go @@ -169,9 +169,10 @@ func (c *Collector) Get() *appsv1.Deployment { Resources: commonSpec.Resources, }}, Volumes: commonSpec.Volumes, - ServiceAccountName: account.JaegerServiceAccountFor(c.jaeger), + ServiceAccountName: account.JaegerServiceAccountFor(c.jaeger, account.CollectorComponent), Affinity: commonSpec.Affinity, Tolerations: commonSpec.Tolerations, + SecurityContext: commonSpec.SecurityContext, }, }, }, diff --git a/pkg/deployment/ingester.go b/pkg/deployment/ingester.go index e9f1f25b8..a5cb23153 100644 --- a/pkg/deployment/ingester.go +++ b/pkg/deployment/ingester.go @@ -146,9 +146,10 @@ func (i *Ingester) Get() *appsv1.Deployment { Resources: commonSpec.Resources, }}, Volumes: commonSpec.Volumes, - ServiceAccountName: account.JaegerServiceAccountFor(i.jaeger), + ServiceAccountName: account.JaegerServiceAccountFor(i.jaeger, account.IngesterComponent), Affinity: commonSpec.Affinity, Tolerations: commonSpec.Tolerations, + SecurityContext: commonSpec.SecurityContext, }, }, }, diff --git a/pkg/deployment/query.go b/pkg/deployment/query.go index 52f81ce8e..c9cc6efa2 100644 --- a/pkg/deployment/query.go +++ b/pkg/deployment/query.go @@ -155,9 +155,10 @@ func (q *Query) Get() *appsv1.Deployment { Resources: commonSpec.Resources, }}, Volumes: commonSpec.Volumes, - ServiceAccountName: account.JaegerServiceAccountFor(q.jaeger), + ServiceAccountName: account.JaegerServiceAccountFor(q.jaeger, account.QueryComponent), Affinity: commonSpec.Affinity, Tolerations: commonSpec.Tolerations, + SecurityContext: commonSpec.SecurityContext, }, }, }, diff --git a/pkg/util/util.go b/pkg/util/util.go index b90fe3c6e..56f8fb53c 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -51,6 +51,8 @@ func Merge(commonSpecs []v1.JaegerCommonSpec) *v1.JaegerCommonSpec { resources := &corev1.ResourceRequirements{} var affinity *corev1.Affinity var tolerations []corev1.Toleration + var securityContext *corev1.PodSecurityContext + var serviceAccount string for _, commonSpec := range commonSpecs { // Merge annotations @@ -79,16 +81,26 @@ func Merge(commonSpecs []v1.JaegerCommonSpec) *v1.JaegerCommonSpec { } tolerations = append(tolerations, commonSpec.Tolerations...) + + if securityContext == nil { + securityContext = commonSpec.SecurityContext + } + + if serviceAccount == "" { + serviceAccount = commonSpec.ServiceAccount + } } return &v1.JaegerCommonSpec{ - Annotations: annotations, - Labels: labels, - VolumeMounts: removeDuplicatedVolumeMounts(volumeMounts), - Volumes: removeDuplicatedVolumes(volumes), - Resources: *resources, - Affinity: affinity, - Tolerations: tolerations, + Annotations: annotations, + Labels: labels, + VolumeMounts: removeDuplicatedVolumeMounts(volumeMounts), + Volumes: removeDuplicatedVolumes(volumes), + Resources: *resources, + Affinity: affinity, + Tolerations: tolerations, + SecurityContext: securityContext, + ServiceAccount: serviceAccount, } } diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index 41066f8ea..0b2e0d736 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -215,6 +215,35 @@ func TestAffinityOverride(t *testing.T) { assert.Nil(t, merged.Affinity.NodeAffinity) } +func TestSecurityContextDefault(t *testing.T) { + generalSpec := v1.JaegerCommonSpec{} + specificSpec := v1.JaegerCommonSpec{} + + merged := Merge([]v1.JaegerCommonSpec{specificSpec, generalSpec}) + + assert.Nil(t, merged.SecurityContext) +} + +func TestSecurityContextOverride(t *testing.T) { + intVal := int64(1000) + generalSpec := v1.JaegerCommonSpec{ + SecurityContext: &corev1.PodSecurityContext{ + RunAsUser: &intVal, + }, + } + specificSpec := v1.JaegerCommonSpec{ + SecurityContext: &corev1.PodSecurityContext{ + RunAsGroup: &intVal, + }, + } + + merged := Merge([]v1.JaegerCommonSpec{specificSpec, generalSpec}) + + assert.NotNil(t, merged.SecurityContext) + assert.NotNil(t, merged.SecurityContext.RunAsGroup) + assert.Nil(t, merged.SecurityContext.RunAsUser) +} + func TestMergeTolerations(t *testing.T) { generalSpec := v1.JaegerCommonSpec{ Tolerations: []corev1.Toleration{{