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

[OTLPGRPC Exporter] Enable OAuth2 client credentials configuration in grpc based otlp exporter #2500

Closed
pavankrish123 opened this issue Feb 16, 2021 · 5 comments
Labels

Comments

@pavankrish123
Copy link
Contributor

pavankrish123 commented Feb 16, 2021

Is your feature request related to a problem? Please describe.

gRPC client from config gRPC module needs to support client credentials (OAuth2) way of handling auth. (exporters).

Instead of using static token, the client configuration must take in client credentials and implicitly fetch and refresh the token as necessary. gRPC client framework already has module to do this. We just need to enable it l.

Describe the solution you'd like
OTLP grpc exporter should be able to use client credentials to perform OAuth2 flow. Something like this is desired along the lines of existing "bearer token" based authx

exporters:
  otlp:
    endpoint: some-grpc:9090
    per_rpc_auth:
      type: client_credentials
      oauth2:
        client_id: someclientidentifier
        client_secret: someclientsecret
        token_url: https://autz.server.com/oauth2/default/v1/token
        scopes: ["some.resource.read"]
@pavankrish123 pavankrish123 changed the title Enable OAuth2 client credentials for oltp grpc based exporter Enable OAuth2 client credentials configuration in grpc based oltp exporter Feb 16, 2021
@pavankrish123
Copy link
Contributor Author

@jpkrohling kindly let me know if the configuration structure is good. I am happy to add the support.

@jpkrohling
Copy link
Member

The config implies that the token would be refreshed during a RPC in case it's expired. I can imagine that we'd have a background process that will refresh tokens actively before they expire, outside of the hot-path. On the other hand, the bearer token is appropriately inside the per_rpc_auth node, as it's the same token being added to every RPC call.

Any suggestions on how we can use a single structure for both cases?

@pavankrish123
Copy link
Contributor Author

pavankrish123 commented Feb 26, 2021

Hi @jpkrohling couple of things

  • As for the proposed OAuth2 client credentials workflow, grpc's OAuth library already has built in mechanism to do the token refresh - we do not have to do anything more other than enabling Oauth as the mechanism in grpc's per rpc auth configuration. The underneath grpc OAuth library handles the token refreshes.

  • As for the static token ("bearer") case, going by comment from @tigrannajaryan Document what PerRPCAuth provides over Headers in GRPCClientSettings #2508 - the case can be handled directly using headers (which is consistent with what HTTP clients are doing), don't think we need custom bearer mechanism for grpcs per rpc auth - unless you think there is something more to it. (PS: I could verify static token case by slapping Bearer: <token> in headers section of grpc exporters)

So the only thing we need to concern is how we can provide configuration option to users in a consistent fashion, if the approach happening in #2229 gets through, something like this can be done.

receivers:
  somereceiver:
    grpc:
      auth:
        authenticator: oidc
exporters:
   someexporter:
      grpc:
        auth:
          authenticator: oauth2

extensions:
  oidc:
    issuer_url: https://auth.example.com/
    issuer_ca_path: /etc/pki/tls/cert.pem
    audience: my-oidc-client
    username_claim: email
    groups_claim: group
    attribute: authorization

  oauth2:
     client_id: someclientidentifier
     client_secret: someclientsecret
     token_url: https://autz.server.com/oauth2/default/v1/token
     scopes: ["some.resource.read"]

service:
  extensions: [oidc, oauth2]
  pipeline:
    traces/toSomewhere:
      receivers: [somereceiver]
      exporters: [someexporter]

Let's hold on to the configuration pattern till #2229 is resolved. For now, Just note that the mechanism to update token is taken care by the underneath grpc libraries, all we have to do is configure.

@jpkrohling
Copy link
Member

As for the static token ("bearer") case, going by comment from @tigrannajaryan #2508 - the case can be handled directly using headers (which is consistent with what HTTP clients are doing), don't think we need custom bearer mechanism for grpcs per rpc auth - unless you think there is something more to it. (PS: I could verify static token case by slapping Bearer: in headers section of grpc exporters)

Missed this part, so, wanted to clarify this point here in addition to #2508: Per RPC Auth is done for every RPC that happens during a connection. HTTP headers are sent only during the phase where the connection is being established. For short-lived HTTP requests, there isn't much difference, but HTTP/2 and gRPC use long-lived connections. For tokens that expire frequently (hourly, for instance), there's a chance that a client's token will get revoked while it still has an open connection to the server. In this case, per-RPC is more appropriate than auth via initial HTTP headers.

@pavankrish123
Copy link
Contributor Author

Thanks @jpkrohling ! This clears a lot for me.

@jrcamp jrcamp added the priority:p2 Medium label Mar 10, 2021
@pavankrish123 pavankrish123 changed the title Enable OAuth2 client credentials configuration in grpc based oltp exporter Enable OAuth2 client credentials configuration in grpc based otlp exporter Mar 24, 2021
@pavankrish123 pavankrish123 changed the title Enable OAuth2 client credentials configuration in grpc based otlp exporter [OTLPGRPC Exporter] Enable OAuth2 client credentials configuration in grpc based otlp exporter Mar 24, 2021
tigrannajaryan pushed a commit to open-telemetry/opentelemetry-collector-contrib that referenced this issue Jun 28, 2021
…n HTTP and gRPC exporters (#3848)

**This is a port of the approved  PR open-telemetry/opentelemetry-collector#3369  from core to contrib per instructions from @tigrannajaryan**

Link to tracking Issue:
open-telemetry/opentelemetry-collector#2785
open-telemetry/opentelemetry-collector#2500
open-telemetry/opentelemetry-collector#2603

**Testing**:

- Unit Tests
- Manual testing by verifying the token is getting automatically refreshed after expiry time in HTTP and gRPC OTLP exporters


These are Manual tests 

1) To check whether the token is actually refreshed, I have set up an echo server that prints the token and I have setup a dev okta oauth2 server with access token life time for 5 mins. I could see the token being refreshed, 

```yaml
extensions:
  oauth2client:
    client_id: 0gI........      
    client_secret: _doAe0NeU.......
    token_url: https://dev-xxxxxxxx.XXX.com/oauth2/default/v1/token
    scopes: ["api.metrics"]
    # timeout for the token client
    timeout: 2s

receivers:
  hostmetrics:
    collection_interval: 20s
    scrapers:
      load:

exporters:
  logging:
  otlp:
    endpoint: localhost:5000
    ca_file: /tmp/certs/ca.pem
    auth:
      authenticator: oauth2client

service:
  extensions: [oauth2client]
  pipelines:
    metrics/agent:
      receivers:
        - hostmetrics
      processors: []
      exporters:
        - logging
        - otlp
```
sample output from server
```
2021/06/07 16:06:11 map[:authority:[localhost:5000] authorization:[Bearer eyJraWQiOiJfamJVQnpzX0RXMHdBUTF[...........]a4wK0VSQ0hpw] content-type:[application/grpc] user-agent:[grpc-go/1.38.0]]


2021/06/07 16:06:32 map[:authority:[localhost:5000] authorization:[Bearer eyJraWQiOiJfamJVQnpzX0RXMHdBUTF[..........]_cNz1zciIg_hJurzUD-5A1_w] content-type:[application/grpc] user-agent:[grpc-go/1.38.0]]
```

2) For an e2e use case, 

I followed the steps from @jpkrohling article [here](https://medium.com/opentelemetry/securing-your-opentelemetry-collector-1a4f9fa5bd6f) and instead of directly using access token by explicitly making curl, I plugged in client secret into auth configuration as below 

(agent yaml)

```yaml
extensions:
  oauth2client:
    client_id: agent
    client_secret: 0d03380f-d0f3-XXX-XXXXXXXXX
    token_url: http://localhost:8080/auth/realms/opentelemetry/protocol/openid-connect/token
    # tls settings for the token client
    tls:
      insecure: true
      ca_file: /tmp/certs/ca.pem
      cert_file: /tmp/certs/cert.pem
      key_file: /tmp/certs/cert-key.pem
    # timeout for the token client
    timeout: 2s

receivers:
  hostmetrics:
    collection_interval: 20s
    scrapers:
      load:

exporters:
  logging:
  otlp:
    endpoint: localhost:56680
    ca_file: /tmp/certs/ca.pem
    auth:
      authenticator: oauth2client

service:
  extensions: [oauth2client]
  pipelines:
    metrics/agent:
      receivers:
        - hostmetrics
      processors: []
      exporters:
        - logging
        - otlp
 ``` 

I could see the metrics coming on the collector side 

```
2021-06-07T16:12:24.924-0700	INFO	loggingexporter/logging_exporter.go:57	MetricsExporter	{"#metrics": 3}
2021-06-07T16:12:44.838-0700	INFO	loggingexporter/logging_exporter.go:57	MetricsExporter	{"#metrics": 3}
2021-06-07T16:15:24.857-0700	INFO	loggingexporter/logging_exporter.go:57	MetricsExporter	{"#metrics": 3}
````

**Documentation:**
 Added README.md
hughesjj pushed a commit to hughesjj/opentelemetry-collector that referenced this issue Apr 27, 2023
)

Bumps [k8s.io/kubectl](https://github.com/kubernetes/kubectl) from 0.25.5 to 0.26.1.
- [Release notes](https://github.com/kubernetes/kubectl/releases)
- [Commits](kubernetes/kubectl@v0.25.5...v0.26.1)

---
updated-dependencies:
- dependency-name: k8s.io/kubectl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants