istio-ecosystem / authservice Goto Github PK
View Code? Open in Web Editor NEWMove OIDC token acquisition out of your app code and into the Istio mesh
License: Apache License 2.0
Move OIDC token acquisition out of your app code and into the Istio mesh
License: Apache License 2.0
{
insertId: "zsre4bfas8ajr"
jsonPayload: {
author: "cfryanr"
component: "hook"
event-GUID: "0fef05e0-eecd-11e9-87f6-8b407be6260a"
event-type: "pull_request"
file: "prow/plugins/approve/approvers/owners.go:164"
func: "k8s.io/test-infra/prow/plugins/approve/approvers.Owners.GetSuggestedApprovers"
level: "warning"
msg: "Couldn't find/suggest approvers for each files. Unapproved: [""]"
org: "istio-ecosystem"
plugin: "approve"
pr: 30
repo: "authservice"
url: "https://github.com/istio-ecosystem/authservice/pull/30"
}
labels: {…}
logName: "projects/istio-testing/logs/hook"
receiveTimestamp: "2019-10-14T21:53:37.741292100Z"
resource: {…}
severity: "ERROR"
timestamp: "2019-10-14T21:53:33Z"
}
Lines 1 to 5 in db27de6
-
Installing the current authservice on k8s/GCP results in the loop during the login in flow, where it got stuck in the authentication request:
https://IDP-DOMAIN/oauth/authorize?client_id=fb142b75-fbc3-454c-983d-6bf12ac08d5b&nonce=%60%97&redirect_uri=https%3A%2F%2F35.222.43.97%2Foauth%2Fcallback&response_type=code&scope=openid&state=
We notice that in the above authentication request, both the nonce
and state
values are invalid/empty.
Here is the authservice
logs:
kubectl logs -f -n istio-system transparent-auth-v1-58d54bcc5f-vlxcl
[2019-09-12 20:32:40.572] [console] [trace] OidcFilter
Server listening on 0.0.0.0:8081
[2019-09-12 20:33:52.160] [console] [trace] Check
[2019-09-12 20:33:52.163] [console] [trace] Process
[2019-09-12 20:33:52.163] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:33:52.163] [console] [trace] Process: checking handler for ://35.222.43.97-/todos
[2019-09-12 20:34:07.280] [console] [trace] Check
[2019-09-12 20:34:07.280] [console] [trace] Process
[2019-09-12 20:34:07.280] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:34:07.280] [console] [trace] Process: checking handler for ://35.222.43.97-/oauth/callback?code=22c2imRlWA&state=
[2019-09-12 20:34:07.740] [console] [trace] Check
[2019-09-12 20:34:07.740] [console] [trace] Process
[2019-09-12 20:34:07.740] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:34:07.740] [console] [trace] Process: checking handler for ://35.222.43.97-/oauth/callback?code=3HZgM779v8&state=
[2019-09-12 20:34:08.065] [console] [trace] Check
[2019-09-12 20:34:08.066] [console] [trace] Process
[2019-09-12 20:34:08.068] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:34:08.069] [console] [trace] Process: checking handler for ://35.222.43.97-/oauth/callback?code=joXtur3t1d&state=
[2019-09-12 20:34:08.484] [console] [trace] Check
[2019-09-12 20:34:08.484] [console] [trace] Process
[2019-09-12 20:34:08.484] [console] [debug] Call from @10.8.1.58 to @10.8.1.72
[2019-09-12 20:34:08.484] [console] [trace] Process: checking handler for ://35.222.43.97-/oauth/callback?code=DT42Zr79IG&state=
We are suspect the RandomGenerator is not working correctly, in oidc_filter.cc
:
common::utilities::RandomGenerator generator;
auto state = generator.Generate(32);
This problem reminds us of a separate problem we encountered where VMs on GCP start with insufficient entropy, causing problem with random generation. Just a thought.
Placeholder issue. Details TBD.
The user should optionally be able to configure logout.path and logout.redirect_to_uri. If they choose to configure either, then they must configure both.
GIVEN The user has configured the logout.path and logout.redirect_to_uri
WHEN The user makes a GET and/or POST to the logout URI, with and/or without cookies,
THEN all of the authservice cookies should be removed (if any)
AND the user's browser should be redirected to GET the configured logout.redirect_to_uri
Currently the authservice fetches both the id token and the access token from the OIDC provider. It then saves the ID token into a browser cookie, and sets the ID token into the Authorization
header for the app.
We believe that some apps would prefer to receive the access token, some apps may want to the ID token, and some apps may want both.
Our suggestion is to make this configurable. One possible way to make this configurable would be to expose two new configuration options:
The name of the http header which the authservice should use to transmit the access token to the app. This could default to Authorization
, since the Authorization
header is typically used for access tokens for APIs. The content of this header would be Bearer <token>
where <token>
is the JWT token value, since this is the standard format for oauth tokens passed via the Authorization
header.
The name of the http header which the authservice should use to transmit the ID token to the app. This could default to X-AuthService-ID-Token
. Perhaps just to be consistent, this should also be passed in the Bearer <token>
format. That way, if the user overrides the default and configures this value to instead be Authentication
then it would be correctly passed in the bearer token format.
If the user accidentally configures both of these options to be the same header name, then perhaps a reasonable behavior would be for the authservice to log a warning and then send only the ID token using that header name (or maybe log an error and abort).
Today you can only choose between OIDC filters using request header matching. We could also support path-based matching (or hostname matching?), so when the Authservice is applied to the gateway you could support multiple apps in the cluster that want to use different OIDC Providers.
This issue #13 is closed and the related PR is merged. But the feature cannot be tested out until envoyproxy accepts, merges, and releases this PR: envoyproxy/envoy#8668
This issue is a reminder to validate that the access feature describe in #13 is working.
Rename internal top level namespace from transparent_auth to authservice to match repository name.
In our first draft of supporting web proxies, we decided not to support basic auth usernames and passwords for the proxy_uri
configuration option.
If we choose to support basic auth to the proxy server in the future, we should probably also support using https to make the "connect" request to the proxy server, so we are not sending the proxy username/password in the clear on the "connect" request's Proxy-Authorization: Basic base64-encoded-proxy-credentials
header.
Also, if we choose to support basic auth to the proxy server in the future, we should consider allowing the @
character in usernames and passwords by introducing the \
character as an escape character. Of course, that would also imply that we would need to support escaping the escape character itself, e.g. \\
.
Web proxies can also require other auth types, but we're not sure how common those would be. See Proxy-Authorization and Proxy-Authenticate for more information.
This is a feature previously proposed by @nickrmc83. I'm creating this github issue as a placeholder for Nick to fill in the details of his proposal.
The goal of this feature is to avoid giving an expired access token to the app for as long as possible by using the refresh token to fetch a new access token, until the refresh token itself expires, at which point the authservice would start a brand new token request.
One possible implementation could be as follows. If the authservice receives a refresh token along with the ID and access tokens, then it would:
Currently, the authservice does not look at the user's tokens inside the cookie on subsequent requests. This choice was perhaps made because Istio already supports adding a Policy (with apiVersion "authentication.istio.io/v1alpha1") to validate JWT tokens on the Authorization
header (see https://istio.io/docs/tasks/security/authn-policy/#end-user-authentication). Assuming that you configure your app to use both the authservice for fetching tokens and the authentication policy for checking tokens, then the app is secured.
However, when the tokens inside that cookie expire, the user will not be able to access the app anymore. Presumably they would need to manually clear that cookie from their browser to convince the authservice to help them fetch new tokens.
Instead, the authservice could check the expiration dates of the tokens from the cookie on each request. A first draft of an improvement would be for the authserive to simply throw away the cookie and pretend that it was not there when it sees that one of the tokens inside the cookie has expired. That way, the authservice would help the user start the flow to obtain new tokens during that same request where it first detected that a token has expired.
A future iteration of this type of functionality could go a step further by using the refresh token, as described in issue #16, but the first draft described here would not need to be so sophisticated.
The ID token and the access token could potentially have different expiration dates. It might be worth considering ignoring one of them if the app is not interested in receiving that token type from the authservice, assuming that there were some way for the user to configure that.
It would also be worth considering if/how to handle opaque access tokens in the context of this feature. Presumably the authservice would have to make an http call to the OIDC server to ask if the token is still valid. Of course, this would have a performance implication. This probably needs more conversation.
This line of thought perhaps opens the bigger question of whether or not the authservice should be doing full token validation of the tokens from the cookie on every request before putting them on the http headers for the app. One advantage of doing so would be that the user would not need to configure the Istio authentication policy for checking tokens, and thus avoid repeating the issuer
and jwksUri
settings between the authservice config and the authentication policy config. Another advantage would be that we could support opaque access tokens, which are not supported by the Istio authentication policy. This probably also needs more conversation.
@nickrmc83 What would you think of adding a feature like this to the beta milestone plan?
At the moment, the authservice only read the json config file upon startup.
Using kubectl apply
to update the configmap for authservice causes the json file inside the container to be updated (after a short delay). It would be possible for the authservice to detect that this file has changed and react appropriately, somehow taking the new configuration into account, without needing to restart the whole container/pod.
If I visit example.com/some_path
and the authservice decides that it needs to redirect me to an IDP to login and get tokens, could the authservice send me back to example.com/some_path
after it obtains the tokens?
At first glance it would appear that this would require some kind of state to be stored in the authservice. But is there another way? For example, could this state be put into another browser cookie to avoid storing the state server-side?
To make the authservice a little easier to configure, we could change the configuration format to take URIs as plain old URI strings instead of as structures of scheme/hostname/port/path.
From Jianfei Hu (@ jianfeih) on istio.slack.com:
would be nice to align the terminology of the config map with actual what /.well-known/oidc-configuration output. the mapping is obvious but can be better
provide a ready to be used oidc client. iirc, the bookinfo demo tutorials somehow assume you get a oidc client app setup (client id, etc) for a certain identity provider, which require some setup out of the sample instruction.
more config editing automation will be great. sed/kubectl/env var combined shows what's going on same time save some error prone editing.
When we moved to auto-generated docs, it looks like some small bits of documentation may have been lost.
Compare https://github.com/istio-ecosystem/authservice/blob/master/docs/README.md with the table from https://github.com/istio-ecosystem/authservice/tree/6dfd1ebd5a61034238fe73d791cb7cbf5262d733/bookinfo-example and resolve the diferences by updating the proto files (the source of the auto-generated docs).
We are trying to setup an oidc provider for authZ and authN with istio in our k8s cluster. We followed this example here: Bookinfo with Authservice Example for the integration.
Below are the details on the setup:
OIDC provider: Keycloak
Grant type: authorization_code
Istio version: 1.5
Authentication flow:
authservice
successfully redirects to Keycloak, where we're able to login successfully.This is the step where authservice fails and gives the error IdP connection error
. The log for the request is as follows:
Check: processing request ://microservice.url.com/appservice/oauth/callback?state=LeCNEqfwA6EUFGNGLt7JALx8jCWkPxjn7qCELbqkKrk&session_state=18f0e3b0-bee2-44a5-b049-6e349dbeda49&code=ddea1ea6-5616-416d-8291-c00bce6f2e9b.18f0e3b0-bee2-44a5-b049-6e349dbeda49.af7e7c31-fd4b-4a66-9856-25d1ac305d3f with filter chain idp_filter_chain
20/03/2020 17:27:48 [2020-03-20 11:57:48.546] [console] [trace] New
20/03/2020 17:27:48 [2020-03-20 11:57:48.547] [console] [trace] OidcFilter
20/03/2020 17:27:48 [2020-03-20 11:57:48.548] [console] [trace] Process
20/03/2020 17:27:48 [2020-03-20 11:57:48.548] [console] [debug] Call from @10.42.5.53 to @10.42.5.58
20/03/2020 17:27:48 [2020-03-20 11:57:48.549] [console] [trace] MatchesCallbackRequest: checking handler for ://microservice.url.com/appservice/oauth/callback?state=LeCNEqfwA6EUFGNGLt7JALx8jCWkPxjn7qCELbqkKrk&session_state=18f0e3b0-bee2-44a5-b049-6e349dbeda49&code=ddea1ea6-5616-416d-8291-c00bce6f2e9b.18f0e3b0-bee2-44a5-b049-6e349dbeda49.af7e7c31-fd4b-4a66-9856-25d1ac305d3f
20/03/2020 17:27:48 [2020-03-20 11:57:48.549] [console] [trace] RetrieveToken
20/03/2020 17:27:48 [2020-03-20 11:57:48.550] [console] [trace] Post
20/03/2020 17:27:48 [2020-03-20 11:57:48.618] [console] [info] Post: HTTP error encountered: stream truncated
20/03/2020 17:27:48 [2020-03-20 11:57:48.618] [console] [info] RetrieveToken: HTTP error encountered: IdP connection error
20/03/2020 17:27:48 [2020-03-20 11:57:48.618] [console] [trace] Request processing complete
20/03/2020 17:27:48 [2020-03-20 11:57:48.619] [console] [trace] Processing completion and deleting state
On further checking the code, I found this error is triggered from here: Authservice oidc filter - Github
To rule out the issues with the configuration, I used OpenID Debugger to manually generate an authorization code and then called the api to exchange it for an api token. I was able to successfully retrieve it, there was no issue with that. But somehow it is failing with authservice.
Could there be something wrong on my end? Has anyone experienced this issue before? Any help appreciated. Let me know if any more details are needed.
Traffic for configured paths and methods (e.g. GET /health) should be allowed to pass the authservice without being redirected to the IDP. For instance an application's marketing landing page or health endpoint may not require a user be logged in to view it.
Both the Istio authn policy and the authz policies (both the deprecated RBAC authz policy and the new authz policy) already allow excluding paths and methods.
Currently any internal IdP whose TLS certificate is not signed by a well-known authority or some delegation thereof will stop working once we start verifying peers correctly. We should make sure it is possible to specify an optional CA certificate for verifying IdP endpoints.
The Pivotal team volunteered to do this.
Commit 2e2be29
WARNING: Download from https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz failed: class java.io.IOException GET returned 403 Forbidden
docker -v
Docker version 18.09.2, build 6247962
lsb_release -a
LSB Version: core-9.20170808ubuntu1-noarch:printing-9.20170808ubuntu1-noarch:security-9.20170808ubuntu1-noarch
Distributor ID: Ubuntu
Description: Ubuntu 18.04 LTS
Release: 18.04 LTS
Codename: bionic
DEBUG: /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_toolchains/rules/rbe_repo/checked_in.bzl:100:9: rbe_ubuntu_clang_gen not using checked in configs as user set attr to 'False'
DEBUG: /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_toolchains/rules/rbe_repo/checked_in.bzl:100:9: rbe_ubuntu_clang_libcxx_gen not using checked in configs as user set attr to 'False'
DEBUG: /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_toolchains/rules/rbe_repo/checked_in.bzl:100:9: rbe_ubuntu_gcc_gen not using checked in configs as user set attr to 'False'
Analyzing: target //src/main:auth_server (1 packages loaded, 0 targets configured)
Analyzing: target //src/main:auth_server (11 packages loaded, 16 targets configured)
Analyzing: target //src/main:auth_server (11 packages loaded, 16 targets configured)
DEBUG: Rule 'com_github_abseil-cpp' indicated that a canonical reproducible form can be obtained by modifying arguments shallow_since = "1562102625 -0400"
DEBUG: Call stack for the definition of repository 'com_github_abseil-cpp' which is a git_repository (rule definition at /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_tools/tools/build_defs/repo/git.bzl:195:18):
- /src/WORKSPACE:88:1
Analyzing: target //src/main:auth_server (22 packages loaded, 148 targets configured)
Analyzing: target //src/main:auth_server (67 packages loaded, 8323 targets configured)
Analyzing: target //src/main:auth_server (77 packages loaded, 8594 targets configured)
INFO: Call stack for the definition of repository 'boost' which is a http_archive (rule definition at /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_tools/tools/build_defs/repo/http.bzl:262:16):
- /src/WORKSPACE:107:1
WARNING: Download from https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz failed: class java.io.IOException GET returned 403 Forbidden
ERROR: An error occurred during the fetch of repository 'boost':
java.io.IOException: Error downloading [https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz] to /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/boost/boost_1_70_0.tar.gz: GET returned 403 Forbidden
INFO: Call stack for the definition of repository 'boringssl' which is a http_archive (rule definition at /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/bazel_tools/tools/build_defs/repo/http.bzl:262:16):
- /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/envoy_api/bazel/envoy_http_archive.bzl:17:5
- /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/envoy/bazel/repositories.bzl:23:5
- /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/envoy/bazel/repositories.bzl:175:5
- /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/envoy/bazel/repositories.bzl:116:5
- /src/WORKSPACE:24:1
ERROR: /src/src/config/BUILD:5:1: //src/config:config depends on @boost//:all in repository @boost which failed to fetch. no such package '@boost//': java.io.IOException: Error downloading [https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz] to /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/boost/boost_1_70_0.tar.gz: GET returned 403 Forbidden
ERROR: Analysis of target '//src/main:auth_server' failed; build aborted: no such package '@boost//': java.io.IOException: Error downloading [https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz] to /root/.cache/bazel/_bazel_root/f8087e59fd95af1ae29e8fcb7ff1a3dc/external/boost/boost_1_70_0.tar.gz: GET returned 403 Forbidden
INFO: Elapsed time: 91.324s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (99 packages loaded, 8858 targets configured)
FAILED: Build did NOT complete successfully (99 packages loaded, 8858 targets configured)
make: *** [Makefile:33: bazel-bin/src/main/auth_server] Error 1
e.g. how to use multiple IDPs, how to use logout, etc.
Authservice server-side sessions store things like your ID token, access token, refresh token, and the url that you originally requested before you were redirected to auth. In the first draft, this is all stored in memory. This has two implications for large-scale production usage:
If the container restarts, those users loses their sessions. This isn't too bad if your IDP has its own sessions with those users, because on their next request the Authservice will redirect to the IDP which will immediately log them in without showing any UI.
If you are scaling the Authservice horizontally, then you need to use session affinity to ensure that each session always lands on the same Authservice instance. Again, if your IDP has its own sessions, then its not too big of a deal for a user to land on the wrong instance of Authservice, as they will transparently be logged in (again) after some redirects. This just puts unnecessary load on the IDP.
Moving session storage to a shared storage layer would fix both of these issues.
That opens the question of which solution(s) would be preferable? e.g. Redis, MySql, others? How do other aspects of Istio do things like this? How is this typically done on k8s?
This is a feature originally proposed by @nickrmc83. I'm creating this github issue as a placeholder for Nick to add more details.
To make the authservice a little easier to configure, give the user the option to configure EITHER the well-known endpoint of their OIDC provider OR the jwks json/endpoint, token endpoint, and authorization endpoint.
Under Deploy Bookinfo Using the Authservice for Token Acquisition + Authorization (Sidecar integration):
at step 1, we have: kubectl -f config/authservice-configmap-template-for-authn-and-authz.yaml
it should be instead: kubectl apply -f config/authservice-configmap-template-for-authn-and-authz.yaml
at step 2.iv we say:
If the callback or logout paths in config/authservice-configmap-template-for-authn.yaml
were edited in a previous step, ..."
here the file should be the same we have applied at step 1 (config/authservice-configmap-template-for-authn-and-authz.yaml
instead of config/authservice-configmap-template-for-authn.yaml
)
Create CI/CD configuration for running builds and test on all commits and MRs.
It should be possible for community members to try the upcoming alpha release without compiling the code or rebuilding the container image.
Therefore, let's allow the configuration (without needing to recompile or build a new container image) of the following:
When the authservice sets the token into the Authorization header for the app, it should follow the OAuth "Bearer Token Usage" standard https://tools.ietf.org/html/rfc6750#section-2.1. Specifically, the token value should be prepended with Bearer
(that's bearer with a capital B followed by a space character).
Per @rshriram's suggestion in the istio slack, we should update https://github.com/istio-ecosystem/authservice/blob/master/bookinfo-example/config/bookinfo-authn-policy-template-adding-reviews.yaml to use the new authN api
I believe it's called RequestAuthentication. Should be a pretty small fix.
Shubham Shukla:
Hi, We implemented authservice to be used with keycloak. Combined with istio auth policies, our end user authentication and authorization(using authorization_code grant) works great!
We also have the requirement for service to service communication within the mesh(background jobs for example). For this we would need to use either resource owner flow or client credential flow. Does authservice support that? If not, with istio what is the recommended way to go about this?
In our previous experiments using the authservice with Istio/k8s we had deployed the authservice as a separate pod.
The goal is to make sure that the approach of deploying it into the same pod works with the current code, and to make sure it is not too hard to configure. The hope is that keeping the communication within the same pod (i.e. on localhost) will make it more efficient/secure.
The Pivotal team offered to test this out.
When the OIDC server redirects the user back to the authservice with the authcode, envoy does not include the scheme
in the request
object passed to the check()
grpc invocation.
You can see in the envoy code in check_request_utils.cc that it intends to read the scheme from the headers and include it in the request object.
However, you can also see in the logs of the sidecar envoy proxy that the header has no scheme
, so the scheme ends up setting set to empty string in the request object.
[2019-10-02 17:07:39.415][21][trace][http] [external/envoy/source/common/http/http1/codec_impl.cc:514] [C1012] message complete
[2019-10-02 17:07:39.415][21][debug][http] [external/envoy/source/common/http/conn_manager_impl.cc:620] [C1012][S3038797389355712708] request headers complete (end_stream=true):
':authority', '35.184.251.112'
':path', '/oauth/callback?code=<REDACTED>&state=somestate'
':method', 'GET'
'cache-control', 'max-age=0'
'upgrade-insecure-requests', '1'
'user-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
'sec-fetch-mode', 'navigate'
'sec-fetch-user', '?1'
'accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3'
'sec-fetch-site', 'cross-site'
'referer', 'https://demo.login.run.pivotal.io/login'
'accept-encoding', 'gzip, deflate, br'
'accept-language', 'en-US,en;q=0.9'
'cookie', '__Host-acme-state-cookie=U_H1gEHrR2Q6ql4HUpnwg7b0FS-d-rBj4sr9FN8SPLLEWO5KoTsZDJA2encWbrI9nhlWv92RKAwNDS_Wox4dzNSxunds1PVKXTNGejhK1w'
'x-forwarded-for', '10.128.15.194'
'x-forwarded-proto', 'https'
'x-envoy-internal', 'true'
'x-request-id', 'eb56154d-3d36-9296-ae58-ba699589bb07'
'x-envoy-decorator-operation', 'authcode-sample-app.default.svc.cluster.local:8080/oauth*'
'x-istio-attributes', 'CksKGGRlc3RpbmF0aW9uLnNlcnZpY2UuaG9zdBIvEi1hdXRoY29kZS1zYW1wbGUtYXBwLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwKSQoXZGVzdGluYXRpb24uc2VydmljZS51aWQSLhIsaXN0aW86Ly9kZWZhdWx0L3NlcnZpY2VzL2F1dGhjb2RlLXNhbXBsZS1hcHAKMQoYZGVzdGluYXRpb24uc2VydmljZS5uYW1lEhUSE2F1dGhjb2RlLXNhbXBsZS1hcHAKKgodZGVzdGluYXRpb24uc2VydmljZS5uYW1lc3BhY2USCRIHZGVmYXVsdApPCgpzb3VyY2UudWlkEkESP2t1YmVybmV0ZXM6Ly9pc3Rpby1pbmdyZXNzZ2F0ZXdheS03NTc1ZmY2NDc4LXJuc3NqLmlzdGlvLXN5c3RlbQ=='
'x-b3-traceid', 'e227b3e674b2fa1470ba2e837fddd97c'
'x-b3-spanid', '70ba2e837fddd97c'
'x-b3-sampled', '1'
'content-length', '0'
It is unclear why the request has no scheme here. We can see in our Chrome browser's debug tools that the redirect from the OIDC server was in fact an https URL, and that the browser followed that redirect by making a GET request to the https URL.
The authservice code puts out a trace log which shows that the request's scheme is empty:
[2019-10-02 17:07:40.408] [console] [trace] Check
[2019-10-02 17:07:40.409] [console] [trace] Process
[2019-10-02 17:07:40.412] [console] [debug] Call from @10.16.0.10 to @10.16.0.18
[2019-10-02 17:07:40.412] [console] [trace] Process: checking handler for ://35.184.251.112-/oauth/callback?code=<REDACTED>&state=somestate
The result is that the if
statement's expression always resolves to false, even in the case where we want it to resolve to true, causing the authservice to never trigger its code which is supposed to exchange the authcode for the token. Instead it starts the token flow from scratch, resulting in a redirect loop which gets halted by the browser.
We need to improve performance for the number in-progress requests. Presently we use blocking grpc and boost network implementations that mean it is conceivable that a trivial DoS could take place and not necessarily by a malicious party.
Once we have finished implementing server-side sessions, we should consider:
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Session_Management_Cheat_Sheet.md
We would like to be able to use the alpha version of authservice with the latest release of Istio, v1.3.0.
In our testing with a pre-repease version of Istio 1.3 we were able to inject an envoy.ext_authz filter into the application's sidecar's inbound envoy.http_connection_manager using a EnvoyFilter configuration. We configured that envoy.ext_authz filter to send all incoming requests to the authservice via grpc check
requests for evaluation.
Unfortunately, this same approach did not work with the first public release of Istio, v1.3.0. We would like to figure out how to make this work before release, because we had planned to document this as the recommended way to use the alpha version of the authservice with Istio on k8s.
We accidentally removed the __Host
prefix from the cookie names. We should probably put that prefix back. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Cookie_prefixes for explanation of that prefix.
To make it easy for the community to try out the alpha version of the authservice, we would like to host the container image in some kind of public registry before releasing.
@liminw offered to find out what is the typical place where istio-ecosystem projects publish their container images for us.
The goal of testing this is to find if it works to have multiple apps which each have their own sidecar and each have their own authservice at the same time. We would especially expect to discover if the authservice provides enough configuration options to make it possible.
e.g. I would guess that each instance of the authservice would need to have unique cookie names if the apps are deployed within the same domain. (Is this a use case that we want to support?)
e.g. I would also guess that each instance of authservice should also have its own cryptor_secret
.
To make it easier for people from the community to try the authservice, and to make it easier for team members to do acceptance testing, we could build a container image for every commit to master which passes unit tests.
Open question: since these would not be numbered releases, where would we want to post these container images?
The pod containing the authservice is experiencing CrashLoopBackOff
due to the log-level flag:
kubectl logs -n istio-system transparent-auth-v1-55b5f5b849-bhx54
ERROR: Unknown command line flag 'log-level'
Changing the Dockerfile CMD line to "--loglevel"
fixes this error. We also noticed that the main function requires "--loglevel"
too.
Fix TODOs
Test the main features of the authservice with envoy, an application to protect, an OIDC provider, and maybe also istio/k8s.
On Istio Slack:
From Shriram Rajagopalan (Tetrate):
Can you convert the readme into an Istio doc example or something?
This is quite useful. You can document it so that more people have access to it
Take this https://github.com/istio-ecosystem/authservice/tree/master/bookinfo-example#authz-with-review-service-optional and make this change part of official bookinfo so that you wont have to build your own.
As suggested above, we could PR the change to Istio's https://github.com/istio/istio/blob/master/samples/bookinfo/src/productpage/productpage.py#L185 file (fixing incoming_headers
to allow the authorization
header to be forwarded on backend app requests).
Second, migrate all your stuff to use new authN api
https://github.com/istio-ecosystem/authservice/blob/master/bookinfo-example/config/bookinfo-authn-policy-template-adding-reviews.yaml specificallty
From a Slack conversation with Enrique Medina Montenegro.
Good morning from the Netherlands 🙂 Here is the info about the proxy issue:
My company uses a corporative proxy --> http://proxy.internal.mycompany.org:8080 <-- to provide access to the Internet
- If any Pod running in our K8s cluster needs outbound Internet access, then it must configure this proxy as env variables --> HTTP_PROXY, HTTPS_PROXY and NO_PROXY
- When using the auth-service, the first redirection to our Azure AD IdP is actually performed by the browser, so there is no issue here
- However, when the auth-service needs to exchange the authorization code for the access token, then it cannot due to not being able to access the Internet
Taking a look at the code, I see that you use the Boost.Beast library for HTTP matters, which claims not to have in its scope the addition of such proxy support:
https://groups.google.com/d/msg/boost-developers-archive/-Zf7f-dfcmA/BUAjLnngBAAJHowever, it seems to be pretty easy:
https://stackoverflow.com/questions/11523829/how-to-add-proxy-support-to-boostasio/11537603#11537603These are the precise logs:
# kubectl logs productpage-v1-5c6798d7d4-mzhs9 -c authservice [2019-12-03 08:04:48.487] [console] [info] RunServer: Server listening on 127.0.0.1:10003 [2019-12-03 08:05:01.305] [console] [trace] Check [2019-12-03 08:05:01.305] [console] [trace] Matches [2019-12-03 08:05:01.305] [console] [debug] Check: processing request ://bookinfo.dev.epocloud.altia.es/productpage with filter chain idp_filter_chain [2019-12-03 08:05:01.305] [console] [trace] New [2019-12-03 08:05:01.306] [console] [trace] OidcFilter [2019-12-03 08:05:01.306] [console] [trace] Process [2019-12-03 08:05:01.306] [console] [debug] Call from @172.16.20.105 to @172.16.135.3 [2019-12-03 08:05:01.306] [console] [info] GetTokenFromCookie: __Host-bookinfo-authservice-id-token-cookie token cookie missing [2019-12-03 08:05:01.306] [console] [info] GetTokenFromCookie: __Host-bookinfo-authservice-access-token-cookie token cookie missing [2019-12-03 08:05:01.306] [console] [trace] Process: checking handler for ://bookinfo.dev.epocloud.altia.es-/productpage [2019-12-03 08:05:01.794] [console] [trace] Check [2019-12-03 08:05:01.794] [console] [trace] Matches [2019-12-03 08:05:01.794] [console] [debug] Check: processing request ://bookinfo.dev.epocloud.altia.es/productpage/oauth/callback?code=OAQABAAIAAACQN9QBRU3jT6bcBQLZNUj7FraunBPo2Anx9gyAxLsdu-bjmfQnfzP9GJZCGakYWsHRzeV_eP89xj8IlweogBgNVF-IJW88VHMjUF2mb1qBgxYUOcOhN4X0RovpJOv25ad5dUCGWpoHmK0n1Q04dDi5dYtbZDAYqPyc_xJmr-rwtSneZoVu7jL16aJ-cF6M96iJQSoZw5fUXlJDaECEls1FKHr6XOhsqtQYgyu8hEL9yt5r3ONyG7Oo6QDWheJi96axsOrOa4toF62bElJeVm4Rsv5C2FFEvMkTQJXXj1hEhc-zk-owBC4D8m5NVGKzRhwphgpkYtRBMyEZtouiJQReKRcGry4KbbXA87LDfM0S5XGX-Kyad7WHV3-s62gFwjW7QqyG0OUq2D6Obm0xIlnmlk6alUOowSAijHHbgf_zXlI34ACRW4pv7SqZ0b6SHtMEioJe0CNFCDBlUVC7Md3_9lCMoonwNoVpEHNE-9eOLKamC-sJyevrATPt6A-WX9HsWcPk3OBwiqnzwMP9DJxj7MLl6KATfLI0mmeswhluYLINKKuvhr6a6oWncaVK9HlsBjH-MYXoRv5kqoaMCh3tU6lNhFMHhUodCcwvPUG4CBDoPQ9UubmEctTyGway7viwDniuqfzP1hj1pVTH09ZrUcVgeSv4sEHeXgupQ4_j7lYtBqWaohHsoQngxVq5HvmSBA8qd_8_Qlxx3vXyGfXuZSFWaZghaKYKrRP7Dm8Dc9R8PvoliTBvL1fLh2KiyePncMfAalIh96NdN27zCLDtbLoNeJpf0NVvp-HXsBckBMxCxLsxMKm22UNLhB3wdSnBEND-HUFxCiPA1IzXsgCGoZW9cFvMFJtbIjyy3ZXkE7DJSewKjW4I7MIVABBEeccgAA&state=0w05_ITARWBE0BfMcW2oSNwFTMtiPRW3Iq_VBkLbAJY&session_state=c302d6d2-c392-424d-97d3-2579814617c4 with filter chain idp_filter_chain [2019-12-03 08:05:01.794] [console] [trace] New [2019-12-03 08:05:01.794] [console] [trace] OidcFilter [2019-12-03 08:05:01.794] [console] [trace] Process [2019-12-03 08:05:01.794] [console] [debug] Call from @172.16.20.105 to @172.16.135.3 [2019-12-03 08:05:01.795] [console] [info] GetTokenFromCookie: __Host-bookinfo-authservice-id-token-cookie token cookie missing [2019-12-03 08:05:01.795] [console] [info] GetTokenFromCookie: __Host-bookinfo-authservice-access-token-cookie token cookie missing [2019-12-03 08:05:01.795] [console] [trace] Process: checking handler for ://bookinfo.dev.epocloud.altia.es-/productpage/oauth/callback?code=OAQABAAIAAACQN9QBRU3jT6bcBQLZNUj7FraunBPo2Anx9gyAxLsdu-bjmfQnfzP9GJZCGakYWsHRzeV_eP89xj8IlweogBgNVF-IJW88VHMjUF2mb1qBgxYUOcOhN4X0RovpJOv25ad5dUCGWpoHmK0n1Q04dDi5dYtbZDAYqPyc_xJmr-rwtSneZoVu7jL16aJ-cF6M96iJQSoZw5fUXlJDaECEls1FKHr6XOhsqtQYgyu8hEL9yt5r3ONyG7Oo6QDWheJi96axsOrOa4toF62bElJeVm4Rsv5C2FFEvMkTQJXXj1hEhc-zk-owBC4D8m5NVGKzRhwphgpkYtRBMyEZtouiJQReKRcGry4KbbXA87LDfM0S5XGX-Kyad7WHV3-s62gFwjW7QqyG0OUq2D6Obm0xIlnmlk6alUOowSAijHHbgf_zXlI34ACRW4pv7SqZ0b6SHtMEioJe0CNFCDBlUVC7Md3_9lCMoonwNoVpEHNE-9eOLKamC-sJyevrATPt6A-WX9HsWcPk3OBwiqnzwMP9DJxj7MLl6KATfLI0mmeswhluYLINKKuvhr6a6oWncaVK9HlsBjH-MYXoRv5kqoaMCh3tU6lNhFMHhUodCcwvPUG4CBDoPQ9UubmEctTyGway7viwDniuqfzP1hj1pVTH09ZrUcVgeSv4sEHeXgupQ4_j7lYtBqWaohHsoQngxVq5HvmSBA8qd_8_Qlxx3vXyGfXuZSFWaZghaKYKrRP7Dm8Dc9R8PvoliTBvL1fLh2KiyePncMfAalIh96NdN27zCLDtbLoNeJpf0NVvp-HXsBckBMxCxLsxMKm22UNLhB3wdSnBEND-HUFxCiPA1IzXsgCGoZW9cFvMFJtbIjyy3ZXkE7DJSewKjW4I7MIVABBEeccgAA&state=0w05_ITARWBE0BfMcW2oSNwFTMtiPRW3Iq_VBkLbAJY&session_state=c302d6d2-c392-424d-97d3-2579814617c4 [2019-12-03 08:05:01.795] [console] [trace] RetrieveToken [2019-12-03 08:05:01.795] [console] [trace] Post [2019-12-03 08:05:01.860] [console] [info] Post: unexpected exception: handshake: WRONG_VERSION_NUMBER [2019-12-03 08:05:01.860] [console] [info] RetrieveToken: HTTP error encountered: IdP connection error
This will simplify the code and will remove the need for the cryptor_secret configuration option.
It will also make the authservice compatible with any version of Istio/envoy, even versions from before the Set-Cookie bug that we fixed (that fix was first included in Istio 1.5).
We are trying to set up the authentication with Istio and keycloak by following the guide here.
We have installed keycloak on our k8s cluster and have exposed it on port 80 as http load balancer.
Keycloak endpoints are http and the 'Require SSL' is set to 'none' at the realm level.
We have configured these endpoints in config/authservice-configmap-template-for-authn.yaml. Istio sidecar injection in enabled in the cluster.
However on applying config/bookinfo-with-authservice-template.yaml, the productpage pod is going to CrashLoopBackOff state with the below error log in the authservice container:
[2020-03-24 08:25:11.162] [console] [error] main: Unexpected error: invalid authorization_uri: uri must be https scheme: http://<ip>/auth/realms/<realm>/protocol/openid-connect/auth
Doesn't authservice support keycloak http endpoints?
In case https endpoints are mandatory for authservice, is there a restriction on how the certificates are generated for keycloak or istio? Should it be a trusted root certificate or can it be a self-signed certificate?
Istio version: 1.4.5
Kubectl version: v1.14.10-gke.17
Such that no auth is required to run docker pull docker.pkg.github.com/istio-ecosystem/authservice/authservice:0.1.0-snapshot.1
This is a follow-up from #12
The goal is to provide a simple way to configure the settings which are currently hardcoded into the source at runtime in such a way that they can be set without needing to recompile or recreate the container image for the authservice.
The Thales team offered to design the approach and implement this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.