1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
|
# 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 :
```
|