Kibana behind GCP Identity Aware Proxy


(Alessandro De Maria) #1

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


(Simone Scarduzio) #2

Hello Alessandro,

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


(Alessandro De Maria) #3

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.


(Simone Scarduzio) #4

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


(Alessandro De Maria) #5

Sure, I will let you know.


(Alessandro De Maria) #6

I think my comment on GCP_IAAP_AUTH_TOKEN was a red herring.

Did you hear back re: ES256?


(Alessandro De Maria) #7

This issue suggests the signature itself is supported?


(Simone Scarduzio) #8

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?


(Alessandro De Maria) #9

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.


(Simone Scarduzio) #10

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.


(Alessandro De Maria) #11

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:[email protected]","x-goog-iap-jwt-assertion":"eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjZCRWVvQSJ9.eyJpc3MiOiJodHRwczovL2Nsb3VkLmdvb2dsZS5jb20vaWFwIiwic3ViIjoiYWNjb3VudHMuZ29vZ2xlLmNvbToxMDAxNjQzNDExNDczNjA4NzgzNjciLCJlbWFpbCI6ImFkZW1hcmlhQGdvb2dsZS5jb20iLCJhdWQiOiIvcHJvamVjdHMvMjUxMTY3MTkzOTAyL2dsb2JhbC9iYWNrZW5kU2VydmljZXMvMzQ4MjUxMDU5NTY3NDg2NjU0NyIsImV4cCI6MTU0NTkwMjE0NiwiaWF0IjoxNTQ1OTAxNTQ2LCJoZCI6Imdvb2dsZS5jb20ifQ.8iADNc8sDxPY6_8bKmpfrai4d221Hh5ZmllTk6PBiX1PmlpDUkTI3S8LpWr-uyNmjmCvN70FQRSfbhdtgk3ujw" XXXXXXXXXXX


(Simone Scarduzio) #12

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"

(Alessandro De Maria) #13

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}


(Alessandro De Maria) #14

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


(Simone Scarduzio) #15

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.


(Simone Scarduzio) #16

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.