Kibana behind GCP Identity Aware Proxy

Hi Simone,

do you have a complete example of how to integrate Kibana behind Google Identity Aware Proxy?

I tried to configure the JWT section to fit IAP Docs but:

  1. Their ES256 algorithm seems unsupported ([ERROR][t.b.r.a.b.r.i.JwtAuthSyncRule] ES256 KeyFactory not available )
  2. They seem to provide multiple signatures, not one.
  3. They don’t seem to documents where their scopes would come from.

Is anybody else using it? Or is anybody else using any other approach?

Using the latest plugin with 5.6.9.

A working example would be great.

Regards
Alessandro

Hello Alessandro,

I reproduced this bug and working with people from jjwt library to find the best solution. Will update.

1 Like

as an update, when testing it appears as if IAP is using different settings than what it is in the documentation.

The actual header seems to be: GCP_IAAP_AUTH_TOKEN
The actual alg seems to be RS256

I wonder if the documentation is incorrect or I am doing something else wrong.

That’s interesting. Maybe google cloud folks can comment on this?

Sure, I will let you know.

1 Like

I think my comment on GCP_IAAP_AUTH_TOKEN was a red herring.

Did you hear back re: ES256?

This issue suggests the signature itself is supported?

No but I’m trying to make this work, do you have an example ES256 private key in the format given out by google cloud?

Wouldn’t you need the public key, like in the list provided by the link on point 2 above? If not I’ll try later from my laptop.

ideally a private and public, to create and validate the token in the unit tests. But also a token and its public key will do.

Hi Simone,

trying again on this now that you have added the EC style signature.
This is my config

 readonlyrest:
 jwt: 
  - name: jwt_provider_1
    signature_algo: EC
    signature_key: "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9e1x7YRZg53A5zIJ0p2ZQ9yTrgPL\nGIf4ntOk+4O2R2+ryIObueyenPXE92tYG1NlKjDNyJLc7tsxi0UUnyxpig==\n-----END PUBLIC KEY-----\n"
    user_claim: email
    header_name: x-goog-iap-jwt-assertion
  access_control_rules:
  - name: Valid JWT token with a writer role
    kibana_access: rw
    jwt_auth:
      name: "jwt_provider_1"
      roles: ["writer"]

however I do not even see an attempt from kibana to interpret the JWT token coming from IAP.

How do I debug this?

example log on Kibana:
{"type":"response","@timestamp":"2018-12-27T09:05:46Z","tags":[],"pid":1,"method":"get","statusCode":304,"req":{"url":"/ui/favicons/favicon-16x16.png","method":"get","headers":{"host":"ZZZZZZ","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36","accept":"image/webp,image/apng,image/*,*/*;q=0.8","referer":"https://ZZZZZZ/app/readonlyrest_kbn","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9,it;q=0.8","if-none-match":"\"6168e24a3738b2bbb81e132e53f2e70367329f22\"","if-modified-since":"Thu, 06 Dec 2018 20:20:33 GMT","x-cloud-trace-context":"86498bc6e57540fa7e0b9d579b34da76/8449657059393905291","x-goog-authenticated-user-id":"accounts.google.com:100164341147360878367","x-goog-authenticated-user-email":"accounts.google.com:ademaria@google.com","x-goog-iap-jwt-assertion":"eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjZCRWVvQSJ9.eyJpc3MiOiJodHRwczovL2Nsb3VkLmdvb2dsZS5jb20vaWFwIiwic3ViIjoiYWNjb3VudHMuZ29vZ2xlLmNvbToxMDAxNjQzNDExNDczNjA4NzgzNjciLCJlbWFpbCI6ImFkZW1hcmlhQGdvb2dsZS5jb20iLCJhdWQiOiIvcHJvamVjdHMvMjUxMTY3MTkzOTAyL2dsb2JhbC9iYWNrZW5kU2VydmljZXMvMzQ4MjUxMDU5NTY3NDg2NjU0NyIsImV4cCI6MTU0NTkwMjE0NiwiaWF0IjoxNTQ1OTAxNTQ2LCJoZCI6Imdvb2dsZS5jb20ifQ.8iADNc8sDxPY6_8bKmpfrai4d221Hh5ZmllTk6PBiX1PmlpDUkTI3S8LpWr-uyNmjmCvN70FQRSfbhdtgk3ujw" XXXXXXXXXXX

Hello @ademaria!

Our Kibana plugin does not validate the JWT directly, it passes it to the ES plugin for inspection. If the ES plugin is able to resolve an identity from the claims, we log in the Kibana user.

So if I was you, I’d make my tests directly with cURL towards port 9200 (Elasticsearch) and wait for a 200 code as a positive test result.

Something along the lines of:

$ curl -ks -u admin:dev https://localhost:9200/_readonlyrest/metadata/current_user | jq

{
  "x-ror-current-group": "ROR (admin)",
  "x-ror-username": "admin",
  "x-ror-kibana-hidden-apps": [],
  "x-ror-kibana_access": "admin",
  "x-ror-available-groups": [
    "ROR (admin)"
  ]
}

But instead of the -u admin:dev you’d use:

 -H 'Authorization: Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjZCRWVvQSJ9.eyJpc3MiOiJodHRwczovL2Nsb3VkLmdvb2dsZS5jb20vaWFwIiwic3ViIjoiYWNjb3VudHMuZ29vZ2xlLmNvbToxMDAxNjQzNDExNDczNjA4NzgzNjciLCJlbWFpbCI6ImFkZW1hcmlhQGdvb2dsZS5jb20iLCJhdWQiOiIvcHJvamVjdHMvMjUxMTY3MTkzOTAyL2dsb2JhbC9iYWNrZW5kU2VydmljZXMvMzQ4MjUxMDU5NTY3NDg2NjU0NyIsImV4cCI6MTU0NTkwMjE0NiwiaWF0IjoxNTQ1OTAxNTQ2LCJoZCI6Imdvb2dsZS5jb20ifQ.8iADNc8sDxPY6_8bKmpfrai4d221Hh5ZmllTk6PBiX1PmlpDUkTI3S8LpWr-uyNmjmCvN70FQRSfbhdtgk3ujw"

Thanks Simone,
i did try and I get the following error:

[myesdb-client-5fff6d8dd4-qrnkq] [2019-01-02T17:03:08,238][WARN ][r.suppressed             ] [myesdb-client-5fff6d8dd4-qrnkq] path: /_readonlyrest/metadata/current_user, params: {} 
[myesdb-client-5fff6d8dd4-qrnkq] java.lang.RuntimeException: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=111, too big. 

I assume I am not passing the key in correctly?

I am using this:
signature_key: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9e1x7YRZg53A5zIJ0p2ZQ9yTrgPL
GIf4ntOk+4O2R2+ryIObueyenPXE92tYG1NlKjDNyJLc7tsxi0UUnyxpig==
-----END PUBLIC KEY-----

The key is taken from https://www.gstatic.com/iap/verify/public_key

{"error":{"root_cause":[{"type":"runtime_exception","reason":"java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=111, too big."}],"type":"runtime_exception","reason":"java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=111, too big.","caused_by":{"type":"invalid_key_spec_exception","reason":"java.security.InvalidKeyException: IOException: DerInputStream.getLength(): lengthTag=111, too big.","caused_by":{"type":"invalid_key_exception","reason":"IOException: DerInputStream.getLength(): lengthTag=111, too big."}}},"status":500}

@sscarduzio do you have anything to suggest re: this error?

Hi Alessandro, thanks for pinging on this thread. It’s been a hectic week.
The first thing to try would be to remove the BEGIN/END lines and concatenate the key in the same line, wrapped by double quotes.

Hi @ademaria, given this configuration:

 jwt:
    - name: jwt1
      signature_key: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9e1x7YRZg53A5zIJ0p2ZQ9yTrgPLGIf4ntOk+4O2R2+ryIObueyenPXE92tYG1NlKjDNyJLc7tsxi0UUnyxpig=="

I have no InvalidKeyException, and the key gets correctly read into a ECPublicKeyImpl object.

However, given your JWT token example, the token can’t be validated. Which is not because it’s expired, but can’t really pass the validation given the public key (the first one in the array you linked):

// 20190115121104
// https://www.gstatic.com/iap/verify/public_key

{
  "2nMJtw": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9e1x7YRZg53A5zIJ0p2ZQ9yTrgPL\nGIf4ntOk+4O2R2+ryIObueyenPXE92tYG1NlKjDNyJLc7tsxi0UUnyxpig==\n-----END PUBLIC KEY-----\n",
  "6BEeoA": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElmi1hJdqtbvdX1INOf5B9dWvkydY\noowHUXiw8ELWzk/YHESNr8vXQoyOuLOEtLZeCQbFkeLUqxYp1sTArKNu/A==\n-----END PUBLIC KEY-----\n",
  "FAWt5w": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8auUAdTS54HmUuIabrTKvWawxmbs\n81kdbzQMV/Tae0EhLgin8qnJ4lklJrxEzksXg5OtBuzE62DIj+CePN20Pg==\n-----END PUBLIC KEY-----\n",
  "f9R3yg": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESqCmEwytkqG6tL6a2GTQGmSNI4jH\nYo5MeDUs7DpETVhCXXLIFrLg2sZvNqw8SGnnonLoeqgOSqRdjJBGt4I6jQ==\n-----END PUBLIC KEY-----\n",
  "rTlk-g": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsm2pfkO5SYLW7vSv3e+XkKBH6SLr\nxPL5a0Z2MwWfJXZXFDQTWzyEwtIADMmS83hp1XqN57Vcu3Nmt7IvhnqR7g==\n-----END PUBLIC KEY-----\n"
}

I have had more luck with the second key listed in the JSON, using that, I get:

JWT expired at 2018-12-27T09:15:46Z. Current time: 2019-01-15T12:17:58Z, a difference of 1652532064 milliseconds.  Allowed clock skew: 0 milliseconds.

So I really think it works, just a matter of selecting the right key, and formatting the key in a single long string without “—BEGIN…” and “—END”, and without the new lines.