352 lines
10 KiB
Markdown
352 lines
10 KiB
Markdown
# Testing with SSL/TLS
|
|
|
|
## Required software
|
|
|
|
The opentelemetry-collector
|
|
[documentation](https://opentelemetry.io/docs/collector/configuration/#setting-up-certificates)
|
|
uses [cfssl](https://github.com/cloudflare/cfssl),
|
|
so we are using cfssl as well here.
|
|
|
|
In addition, install `openssl`, which provides tooling for testing.
|
|
|
|
## Generating CERT
|
|
|
|
### Generating CA CERT
|
|
|
|
First, write a CA request file in json, named `ca_csr.json`
|
|
|
|
It should contains the following data:
|
|
|
|
```console
|
|
shell> cat ca_csr.json
|
|
{
|
|
"hosts": ["localhost", "127.0.0.1"],
|
|
"key": {
|
|
"algo": "rsa",
|
|
"size": 2048
|
|
},
|
|
"names": [
|
|
{
|
|
"O": "OpenTelemetry CA Example"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Then, generate a CA certificate:
|
|
|
|
```console
|
|
shell> cfssl genkey -initca ca_csr.json | cfssljson -bare ca
|
|
2022/12/13 16:42:57 [INFO] generate received request
|
|
2022/12/13 16:42:57 [INFO] received CSR
|
|
2022/12/13 16:42:57 [INFO] generating key: rsa-2048
|
|
2022/12/13 16:42:57 [INFO] encoded CSR
|
|
2022/12/13 16:42:57 [INFO] signed certificate with serial number 78705522450145914781445058194934247010984259280
|
|
```
|
|
|
|
This will create three files, `ca.csr`, `ca.pem` and `ca-key.pem`
|
|
|
|
Congratulation, "OpenTelemetry CA Example" is now a CA certification
|
|
authority, with signing keys.
|
|
|
|
### Generating Client CERT
|
|
|
|
Second, write a certificate request file in json, named `client_csr.json`,
|
|
for the opentelemetry-cpp client.
|
|
|
|
It should contains the following data:
|
|
|
|
```console
|
|
shell> cat client_csr.json
|
|
{
|
|
"hosts": ["localhost", "127.0.0.1"],
|
|
"key": {
|
|
"algo": "rsa",
|
|
"size": 2048
|
|
},
|
|
"names": [
|
|
{
|
|
"O": "OpenTelemetry Client Example"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Note that the name ("OpenTelemetry Client Example") should be different
|
|
from the CA authority name ("OpenTelemetry CA Example"),
|
|
otherwise the client certificate will be self-signed, and rejected later in SSL/TLS.
|
|
|
|
Now, use the CA certificate generated in the previous step
|
|
to create and sign a new client certificate.
|
|
|
|
```console
|
|
shell> cfssl gencert -ca ca.pem -ca-key ca-key.pem client_csr.json | cfssljson -bare client_cert
|
|
2022/12/13 16:50:18 [INFO] generate received request
|
|
2022/12/13 16:50:18 [INFO] received CSR
|
|
2022/12/13 16:50:18 [INFO] generating key: rsa-2048
|
|
2022/12/13 16:50:18 [INFO] encoded CSR
|
|
2022/12/13 16:50:18 [INFO] signed certificate with serial number 579932794730090029542135367576037344135399122179
|
|
```
|
|
|
|
This will create three files, `client_cert.csr`, `client_cert.pem` and `client_cert-key.pem`
|
|
|
|
### Generating Server CERT
|
|
|
|
Third and likewise, write a certificate request file in json, named `server_csr.json`,
|
|
for the opentelemetry server (the opentelemetry-collector)
|
|
|
|
It should contains the following data:
|
|
|
|
```console
|
|
shell> cat server_csr.json
|
|
{
|
|
"hosts": ["localhost", "127.0.0.1"],
|
|
"key": {
|
|
"algo": "rsa",
|
|
"size": 2048
|
|
},
|
|
"names": [
|
|
{
|
|
"O": "OpenTelemetry Server Example"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Likewise, use a different name from the CA authority name.
|
|
|
|
Use the CA certificate to create and sign a new server certificate.
|
|
|
|
```console
|
|
shell> cfssl gencert -ca ca.pem -ca-key ca-key.pem server_csr.json | cfssljson -bare server_cert
|
|
2022/12/13 17:04:40 [INFO] generate received request
|
|
2022/12/13 17:04:40 [INFO] received CSR
|
|
2022/12/13 17:04:40 [INFO] generating key: rsa-2048
|
|
2022/12/13 17:04:40 [INFO] encoded CSR
|
|
2022/12/13 17:04:40 [INFO] signed certificate with serial number 332420451189450993545238745169293824985460186638
|
|
```
|
|
|
|
This will create three files, `server_cert.csr`, `server_cert.pem` and `server_cert-key.pem`
|
|
|
|
### Verify certificates
|
|
|
|
Verify the certificates generated, using `openssl`:
|
|
|
|
```console
|
|
shell> openssl verify -CAfile ca.pem server_cert.pem client_cert.pem
|
|
server_cert.pem: OK
|
|
client_cert.pem: OK
|
|
```
|
|
|
|
Useful commands, to inspect certificates if needed (output not shown here)
|
|
|
|
```console
|
|
shell> openssl x509 -in ca.pem -text
|
|
```
|
|
|
|
```console
|
|
shell> openssl x509 -in client_cert.pem -text
|
|
```
|
|
|
|
```console
|
|
shell> openssl x509 -in server_cert.pem -text
|
|
```
|
|
|
|
## OpenTelemetry SSL clients
|
|
|
|
### Simulated client, for testing
|
|
|
|
Use `openssl` to simulate an opentelemetry-cpp client connecting to port 4318:
|
|
|
|
```console
|
|
shell> openssl s_client -connect localhost:4318 -CAfile ca.pem -cert client_cert.pem -key client_cert-key.pem
|
|
```
|
|
|
|
### OTLP HTTP Client
|
|
|
|
Use the example `example_otlp_http` client to connect to an OTLP HTTP server:
|
|
|
|
```console
|
|
shell> export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://localhost:4318/v1/traces
|
|
shell> export OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE=ca.pem
|
|
shell> export OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE=client_cert.pem
|
|
shell> export OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY=client_cert-key.pem
|
|
shell> example_otlp_http
|
|
```
|
|
|
|
## OpenTelemetry SSL servers
|
|
|
|
### Simulated server, for testing
|
|
|
|
Use `openssl` to simulate an opentelemetry-collector process serving port 4318:
|
|
|
|
```console
|
|
shell> openssl s_server -accept 4318 -CAfile ca.pem -cert server_cert.pem -key server_cert-key.pem
|
|
Using default temp DH parameters
|
|
ACCEPT
|
|
```
|
|
|
|
This command does not return,
|
|
the server waits for SSL connections (Use CTRL-C to quit).
|
|
|
|
### OTLP HTTP Server
|
|
|
|
To use a server that:
|
|
|
|
- implements OTLP HTTP
|
|
- supports SSL
|
|
|
|
use the opentelemetry-collector,
|
|
configured to use SSL/TLS for receivers:
|
|
|
|
```console
|
|
shell> cat otel-collector-config-ssl.yaml
|
|
receivers:
|
|
otlp:
|
|
protocols:
|
|
http:
|
|
tls:
|
|
ca_file: ca.pem
|
|
cert_file: server_cert.pem
|
|
key_file: server_cert-key.pem
|
|
...
|
|
```
|
|
|
|
For example:
|
|
|
|
```console
|
|
shell> /path/to/bin/otelcorecol_linux_amd64 --config /path/to/otel-config-ssl.yaml
|
|
```
|
|
|
|
Note, the `example/http/http_example` can not be used (it understands neither SSL
|
|
nor OTLP HTTP).
|
|
|
|
## Testing SSL on the wire
|
|
|
|
### Fake client with fake server
|
|
|
|
This configuration tests nothing in opentelemetry,
|
|
but is useful to understand what a nominal SSL communication between a
|
|
client and a server should look like.
|
|
|
|
### Real client with fake server
|
|
|
|
In this configuration, we can test that the opentelemetry-cpp
|
|
client actually sends SSL traffic on the wire.
|
|
|
|
### Fake client with real server
|
|
|
|
In this configuration, we can test that the opentelemetry-collector
|
|
server actually accepts SSL traffic on the wire.
|
|
This can be used to verify the client keys are working properly.
|
|
|
|
## Full integration test with SSL
|
|
|
|
Start an opentelemetry-collector, configured to use SSL/TLS.
|
|
|
|
```console
|
|
shell> /path/to/bin/otelcorecol_linux_amd64 --config /path/to/otel-config-ssl.yaml
|
|
...
|
|
2022-12-13T18:03:21.140+0100 info otlpreceiver@v0.66.0/otlp.go:89 Starting HTTP server {"kind": "receiver", "name": "otlp", "pipeline": "metrics", "endpoint": "0.0.0.0:4318"}
|
|
2022-12-13T18:03:21.141+0100 info service/pipelines.go:106 Receiver started. {"kind": "receiver", "name": "otlp", "pipeline": "metrics"}
|
|
2022-12-13T18:03:21.141+0100 info service/pipelines.go:102 Receiver is starting... {"kind": "receiver", "name": "otlp", "pipeline": "traces"}
|
|
2022-12-13T18:03:21.141+0100 info service/pipelines.go:106 Receiver started. {"kind": "receiver", "name": "otlp", "pipeline": "traces"}
|
|
2022-12-13T18:03:21.141+0100 info service/service.go:105 Everything is ready. Begin running and processing data.
|
|
```
|
|
|
|
Start the example_otlp_http client, configured to use SSL/TLS.
|
|
|
|
```console
|
|
shell> export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://localhost:4318/v1/traces
|
|
shell> export OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE=ca.pem
|
|
shell> export OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE=client_cert.pem
|
|
shell> export OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY=client_cert-key.pem
|
|
shell> example_otlp_http
|
|
```
|
|
|
|
The opentelemetry-collector process receives data, as seen in logs:
|
|
|
|
```console
|
|
2022-12-13T18:05:36.611+0100 info TracesExporter {"kind": "exporter", "data_type": "traces", "name": "logging", "#spans": 4}
|
|
2022-12-13T18:05:36.611+0100 info ResourceSpans #0
|
|
Resource SchemaURL:
|
|
Resource attributes:
|
|
-> service.name: Str(unknown_service)
|
|
-> telemetry.sdk.version: Str(1.8.1)
|
|
-> telemetry.sdk.name: Str(opentelemetry)
|
|
-> telemetry.sdk.language: Str(cpp)
|
|
ScopeSpans #0
|
|
ScopeSpans SchemaURL:
|
|
InstrumentationScope foo_library 1.8.1
|
|
Span #0
|
|
Trace ID : ebbd7e13e9cdfb05f0ca9ed4b0cdf6c0
|
|
Parent ID : 042ae76539c294c6
|
|
ID : c87b21d63c505bae
|
|
Name : f1
|
|
Kind : Internal
|
|
Start time : 2022-12-13 17:05:36.482165738 +0000 UTC
|
|
End time : 2022-12-13 17:05:36.482170938 +0000 UTC
|
|
Status code : Unset
|
|
Status message :
|
|
ResourceSpans #1
|
|
Resource SchemaURL:
|
|
Resource attributes:
|
|
-> service.name: Str(unknown_service)
|
|
-> telemetry.sdk.version: Str(1.8.1)
|
|
-> telemetry.sdk.name: Str(opentelemetry)
|
|
-> telemetry.sdk.language: Str(cpp)
|
|
ScopeSpans #0
|
|
ScopeSpans SchemaURL:
|
|
InstrumentationScope foo_library 1.8.1
|
|
Span #0
|
|
Trace ID : ebbd7e13e9cdfb05f0ca9ed4b0cdf6c0
|
|
Parent ID : 042ae76539c294c6
|
|
ID : 801227b9ee6d3b03
|
|
Name : f1
|
|
Kind : Internal
|
|
Start time : 2022-12-13 17:05:36.487636362 +0000 UTC
|
|
End time : 2022-12-13 17:05:36.487641983 +0000 UTC
|
|
Status code : Unset
|
|
Status message :
|
|
ResourceSpans #2
|
|
Resource SchemaURL:
|
|
Resource attributes:
|
|
-> service.name: Str(unknown_service)
|
|
-> telemetry.sdk.version: Str(1.8.1)
|
|
-> telemetry.sdk.name: Str(opentelemetry)
|
|
-> telemetry.sdk.language: Str(cpp)
|
|
ScopeSpans #0
|
|
ScopeSpans SchemaURL:
|
|
InstrumentationScope foo_library 1.8.1
|
|
Span #0
|
|
Trace ID : ebbd7e13e9cdfb05f0ca9ed4b0cdf6c0
|
|
Parent ID : 6489f2ada8d95da0
|
|
ID : 042ae76539c294c6
|
|
Name : f2
|
|
Kind : Internal
|
|
Start time : 2022-12-13 17:05:36.482154908 +0000 UTC
|
|
End time : 2022-12-13 17:05:36.488641122 +0000 UTC
|
|
Status code : Unset
|
|
Status message :
|
|
ResourceSpans #3
|
|
Resource SchemaURL:
|
|
Resource attributes:
|
|
-> service.name: Str(unknown_service)
|
|
-> telemetry.sdk.version: Str(1.8.1)
|
|
-> telemetry.sdk.name: Str(opentelemetry)
|
|
-> telemetry.sdk.language: Str(cpp)
|
|
ScopeSpans #0
|
|
ScopeSpans SchemaURL:
|
|
InstrumentationScope foo_library 1.8.1
|
|
Span #0
|
|
Trace ID : ebbd7e13e9cdfb05f0ca9ed4b0cdf6c0
|
|
Parent ID :
|
|
ID : 6489f2ada8d95da0
|
|
Name : library
|
|
Kind : Internal
|
|
Start time : 2022-12-13 17:05:36.482136052 +0000 UTC
|
|
End time : 2022-12-13 17:05:36.489263125 +0000 UTC
|
|
Status code : Unset
|
|
Status message :
|
|
```
|