Skip to content

Commit

Permalink
Make RHOL Elasticsearch cert-management feature optional
Browse files Browse the repository at this point in the history
The reason is that the cert-management is not supported on OCP 4.6.
The feature was added in RHOL 5.2 shipped on OCP 4.7.

Signed-off-by: Pavol Loffay <[email protected]>
  • Loading branch information
pavolloffay committed Mar 23, 2022
1 parent e78ca97 commit 67650d6
Show file tree
Hide file tree
Showing 12 changed files with 817 additions and 35 deletions.
17 changes: 15 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,22 @@ ARG TARGETARCH
# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} GO111MODULE=on go build -ldflags="-X ${VERSION_PKG}.version=${VERSION} -X ${VERSION_PKG}.buildDate=${VERSION_DATE} -X ${VERSION_PKG}.defaultJaeger=${JAEGER_VERSION}" -a -o jaeger-operator main.go

FROM gcr.io/distroless/static:nonroot
FROM registry.access.redhat.com/ubi8/ubi

ENV USER_UID=1001 \
USER_NAME=jaeger-operator

RUN INSTALL_PKGS="openssl" && \
yum install -y $INSTALL_PKGS && \
rpm -V $INSTALL_PKGS && \
yum clean all && \
mkdir /tmp/_working_dir && \
chmod og+w /tmp/_working_dir

WORKDIR /
COPY --from=builder /workspace/jaeger-operator .
USER 65532:65532
COPY scripts/cert_generation.sh scripts/cert_generation.sh

USER ${USER_UID}:${USER_UID}

ENTRYPOINT ["/jaeger-operator"]
6 changes: 6 additions & 0 deletions apis/v1/jaeger_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,12 @@ type ElasticsearchSpec struct {
// +optional
DoNotProvision bool `json:"doNotProvision,omitempty"`

// Whether Elasticsearch cert management feature should be used.
// This is a preferred setting for new Jaeger deployments on OCP versions newer than 4.6.
// The cert management feature was added to Red Hat Openshift logging 5.2 in OCP 4.7.
// +optional
UseESCertManagement *bool `json:"useESCertManagement,omitempty"`

// +optional
Image string `json:"image,omitempty"`

Expand Down
5 changes: 5 additions & 0 deletions apis/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bundle/manifests/jaegertracing.io_jaegers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9540,6 +9540,8 @@ spec:
type: object
type: array
x-kubernetes-list-type: atomic
useESCertManagement:
type: boolean
type: object
esIndexCleaner:
properties:
Expand Down
2 changes: 2 additions & 0 deletions config/crd/bases/jaegertracing.io_jaegers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9539,6 +9539,8 @@ spec:
type: object
type: array
x-kubernetes-list-type: atomic
useESCertManagement:
type: boolean
type: object
esIndexCleaner:
properties:
Expand Down
7 changes: 7 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -37104,6 +37104,13 @@ Resource Types:
<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>useESCertManagement</b></td>
<td>boolean</td>
<td>
<br/>
</td>
<td>false</td>
</tr></tbody>
</table>

Expand Down
33 changes: 32 additions & 1 deletion pkg/controller/jaeger/jaeger_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"

v1 "github.com/jaegertracing/jaeger-operator/apis/v1"
"github.com/jaegertracing/jaeger-operator/pkg/storage"
"github.com/jaegertracing/jaeger-operator/pkg/strategy"
"github.com/jaegertracing/jaeger-operator/pkg/tracing"
)
Expand Down Expand Up @@ -210,7 +211,37 @@ func (r *ReconcileJaeger) apply(ctx context.Context, jaeger v1.Jaeger, str strat
return jaeger, tracing.HandleError(err, span)
}

// TODO this can be removed after previously released version is using cert management from EO e.g. in 1.32.0
// ES cert handling requires secrets from environment
// therefore running this here and not in the strategy
if v1.ShouldInjectOpenShiftElasticsearchConfiguration(jaeger.Spec.Storage) &&
// generate the certs only if cert management is disabled
(jaeger.Spec.Storage.Elasticsearch.UseESCertManagement == nil ||
*jaeger.Spec.Storage.Elasticsearch.UseESCertManagement == false) {

opts := client.MatchingLabels(map[string]string{
"app.kubernetes.io/instance": jaeger.Name,
"app.kubernetes.io/managed-by": "jaeger-operator",
})
secrets := &corev1.SecretList{}
if err := r.rClient.List(ctx, secrets, opts); err != nil {
jaeger.Status.Phase = v1.JaegerPhaseFailed
if err := r.client.Status().Update(ctx, &jaeger); err != nil {
// we let it return the real error later
jaeger.Logger().WithError(err).Error("failed to store the failed status into the current CustomResource after preconditions")
}
return jaeger, tracing.HandleError(err, span)
}
secretsForNamespace := r.getSecretsForNamespace(secrets.Items, jaeger.Namespace)

es := &storage.ElasticsearchDeployment{Jaeger: &jaeger, CertScript: "./scripts/cert_generation.sh", Secrets: secretsForNamespace}
err = es.CreateCerts()
if err != nil {
es.Jaeger.Logger().WithError(err).Error("failed to create Elasticsearch certificates, Elasticsearch won't be deployed")
return jaeger, err
}
str = str.WithSecrets(append(str.Secrets(), es.ExtractSecrets()...))
}

if err := r.applySecrets(ctx, jaeger, str.Secrets()); err != nil {
return jaeger, tracing.HandleError(err, span)
}
Expand Down
84 changes: 58 additions & 26 deletions pkg/storage/elasticsearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,46 @@ import (
"strconv"
"strings"

esv1 "github.com/openshift/elasticsearch-operator/apis/logging/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

esv1 "github.com/openshift/elasticsearch-operator/apis/logging/v1"

v1 "github.com/jaegertracing/jaeger-operator/apis/v1"
"github.com/jaegertracing/jaeger-operator/pkg/util"
)

const (
volumeName = "certs"
volumeMountPath = "/certs"
caPath = volumeMountPath + "/ca-bundle.crt"
keyPath = volumeMountPath + "/tls.key"
certPath = volumeMountPath + "/tls.crt"
volumeName = "certs"
volumeMountPath = "/certs"
caPathESCerManagement = volumeMountPath + "/ca-bundle.crt"
keyPathESCertManagement = volumeMountPath + "/tls.key"
certPathESCertManagement = volumeMountPath + "/tls.crt"
caPath = volumeMountPath + "/ca"
keyPath = volumeMountPath + "/key"
certPath = volumeMountPath + "/cert"
)

func (ed *ElasticsearchDeployment) getCertPath() string {
if ed.Jaeger.Spec.Storage.Elasticsearch.UseESCertManagement != nil && *ed.Jaeger.Spec.Storage.Elasticsearch.UseESCertManagement {
return certPathESCertManagement
}
return certPath
}

func (ed *ElasticsearchDeployment) getCertKeyPath() string {
if ed.Jaeger.Spec.Storage.Elasticsearch.UseESCertManagement != nil && *ed.Jaeger.Spec.Storage.Elasticsearch.UseESCertManagement {
return keyPathESCertManagement
}
return keyPath
}

func (ed *ElasticsearchDeployment) getCertCaPath() string {
if ed.Jaeger.Spec.Storage.Elasticsearch.UseESCertManagement != nil && *ed.Jaeger.Spec.Storage.Elasticsearch.UseESCertManagement {
return caPathESCerManagement
}
return caPath
}

// ElasticsearchDeployment represents an ES deployment for Jaeger
type ElasticsearchDeployment struct {
Jaeger *v1.Jaeger
Expand All @@ -35,9 +58,9 @@ func (ed *ElasticsearchDeployment) injectArguments(container *corev1.Container)
container.Args = append(container.Args, "--es.tls.enabled=true")
}
container.Args = append(container.Args,
"--es.tls.ca="+caPath,
"--es.tls.cert="+certPath,
"--es.tls.key="+keyPath)
"--es.tls.ca="+ed.getCertCaPath(),
"--es.tls.cert="+ed.getCertPath(),
"--es.tls.key="+ed.getCertKeyPath())

if util.FindItem("--es.timeout", container.Args) == "" {
container.Args = append(container.Args, "--es.timeout=15s")
Expand All @@ -57,9 +80,9 @@ func (ed *ElasticsearchDeployment) injectArguments(container *corev1.Container)
container.Args = append(container.Args, "--es-archive.tls.enabled=true")
}
container.Args = append(container.Args,
"--es-archive.tls.ca="+caPath,
"--es-archive.tls.cert="+certPath,
"--es-archive.tls.key="+keyPath,
"--es-archive.tls.ca="+ed.getCertCaPath(),
"--es-archive.tls.cert="+ed.getCertPath(),
"--es-archive.tls.key="+ed.getCertKeyPath(),
)
if util.FindItem("--es-archive.timeout", container.Args) == "" {
container.Args = append(container.Args, "--es-archive.timeout=15s")
Expand All @@ -82,7 +105,7 @@ func (ed *ElasticsearchDeployment) InjectStorageConfiguration(p *corev1.PodSpec)
Name: volumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: jaegerESSecretName(ed.Jaeger.Spec.Storage.Elasticsearch.Name),
SecretName: jaegerESSecretName(*ed.Jaeger),
},
},
})
Expand All @@ -103,7 +126,7 @@ func (ed *ElasticsearchDeployment) InjectSecretsConfiguration(p *corev1.PodSpec)
Name: volumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: jaegerESSecretName(ed.Jaeger.Spec.Storage.Elasticsearch.Name),
SecretName: jaegerESSecretName(*ed.Jaeger),
},
},
})
Expand All @@ -113,9 +136,9 @@ func (ed *ElasticsearchDeployment) InjectSecretsConfiguration(p *corev1.PodSpec)
p.Containers[0].Args[1] = fmt.Sprintf("https://%s:9200", ed.Jaeger.Spec.Storage.Elasticsearch.Name)
p.Containers[0].Env = append(p.Containers[0].Env,
corev1.EnvVar{Name: "ES_TLS", Value: "true"},
corev1.EnvVar{Name: "ES_TLS_CA", Value: caPath},
corev1.EnvVar{Name: "ES_TLS_KEY", Value: keyPath},
corev1.EnvVar{Name: "ES_TLS_CERT", Value: certPath},
corev1.EnvVar{Name: "ES_TLS_CA", Value: ed.getCertCaPath()},
corev1.EnvVar{Name: "ES_TLS_KEY", Value: ed.getCertKeyPath()},
corev1.EnvVar{Name: "ES_TLS_CERT", Value: ed.getCertKeyPath()},
corev1.EnvVar{Name: "SHARDS", Value: strconv.Itoa(int(ed.Jaeger.Spec.Storage.Elasticsearch.NodeCount))},
corev1.EnvVar{Name: "REPLICAS", Value: strconv.Itoa(calculateReplicaShards(ed.Jaeger.Spec.Storage.Elasticsearch.RedundancyPolicy, int(ed.Jaeger.Spec.Storage.Elasticsearch.NodeCount)))},
)
Expand Down Expand Up @@ -143,6 +166,14 @@ func (ed *ElasticsearchDeployment) Elasticsearch() *esv1.Elasticsearch {
if ed.Jaeger.Spec.Storage.Elasticsearch.Resources != nil {
res = *ed.Jaeger.Spec.Storage.Elasticsearch.Resources
}

annotations := map[string]string{}
if ed.Jaeger.Spec.Storage.Elasticsearch.UseESCertManagement != nil && *ed.Jaeger.Spec.Storage.Elasticsearch.UseESCertManagement == true {
annotations["logging.openshift.io/elasticsearch-cert-management"] = "true"
// The value has to match searchguard configuration
// https://github.com/openshift/origin-aggregated-logging/blob/50126fb8e0c602e9c623d6a8599857aaf98f80f8/elasticsearch/sgconfig/roles_mapping.yml#L34
annotations[fmt.Sprintf("logging.openshift.io/elasticsearch-cert.%s", jaegerESSecretName(*ed.Jaeger))] = "user.jaeger"
}
return &esv1.Elasticsearch{
ObjectMeta: metav1.ObjectMeta{
Namespace: ed.Jaeger.Namespace,
Expand All @@ -157,12 +188,7 @@ func (ed *ElasticsearchDeployment) Elasticsearch() *esv1.Elasticsearch {
// to manipulate with objects created by ES operator.
//"app.kubernetes.io/managed-by": "jaeger-operator",
},
Annotations: map[string]string{
"logging.openshift.io/elasticsearch-cert-management": "true",
// The value has to match searchguard configuration
// https://github.com/openshift/origin-aggregated-logging/blob/50126fb8e0c602e9c623d6a8599857aaf98f80f8/elasticsearch/sgconfig/roles_mapping.yml#L34
fmt.Sprintf("logging.openshift.io/elasticsearch-cert.%s", jaegerESSecretName(ed.Jaeger.Spec.Storage.Elasticsearch.Name)): "user.jaeger",
},
Annotations: annotations,
OwnerReferences: []metav1.OwnerReference{util.AsOwner(ed.Jaeger)},
},
Spec: esv1.ElasticsearchSpec{
Expand Down Expand Up @@ -225,6 +251,12 @@ func calculateReplicaShards(policyType esv1.RedundancyPolicyType, dataNodes int)
}
}

func jaegerESSecretName(elasticsearch string) string {
return fmt.Sprintf("jaeger-%s", elasticsearch)
func jaegerESSecretName(jaeger v1.Jaeger) string {
prefix := ""
// ES cert management creates cert named jaeger-<elasticsearch-name>
// Cert management in Jaeger creates cert named <jaeger-name>-jaeger-elasticsearch
if jaeger.Spec.Storage.Elasticsearch.UseESCertManagement == nil || !*jaeger.Spec.Storage.Elasticsearch.UseESCertManagement {
prefix = jaeger.Name + "-"
}
return fmt.Sprintf("%sjaeger-%s", prefix, jaeger.Spec.Storage.Elasticsearch.Name)
}
Loading

0 comments on commit 67650d6

Please sign in to comment.