Extract JWT claims as string lists under request.auth.claims[] for RBAC#1906
Extract JWT claims as string lists under request.auth.claims[] for RBAC#1906lei-tang wants to merge 7 commits intoistio:masterfrom
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: If they are not already assigned, you can assign the PR to them by writing The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
* Add the groups JWT claims to the attribute request.auth.groups * Fix lint errors * Simplify the code * Fix lint error * Simplify the code * Add a test * Fix the test error
|
/cc @liminw |
|
/cc @diemtvu |
|
/cc @qiwzhang |
d8eda04 to
a87542f
Compare
src/envoy/utils/authn.cc
Outdated
| [istio::utils::AttributeName::kAuthDerivedClaims] | ||
| .mutable_struct_value(); | ||
| ::google::protobuf::ListValue* value = | ||
| (*s->mutable_fields())["groups"].mutable_list_value(); |
There was a problem hiding this comment.
Please use new styple for loop
for (const auto& group : origin.groups())
diemtvu
left a comment
There was a problem hiding this comment.
Overall, I think we should change the way we populate and passing claims. First, we should change the type under JwtPayload to use protobuf::Struct (https://github.com/istio/proxy/blob/master/src/istio/authn/context.proto#L37), so we it's more flexible to keep all claims, instead of just string. There may be an util to convert Json object to proto struct, if you are lucky. Though it's should be ok to write one, and 'normalize' the type (e.g always keep as string array for certain types).
After that, in this part of the code, you simply need to set the 'request.auth.claims' to that struct without any modification.
df22cea to
1549b46
Compare
1549b46 to
47d2ea4
Compare
|
/cc @wattli |
|
This PR puts the groups claim (e.g., "groups: group1") in a JWT under the key request.auth.claims[groups] in the dynamic metadata (this is to be consistent with istio/istio#7747). The change of JwtPayload in context.proto to use protobuf::Struct can be implemented in a separate PR. |
src/envoy/utils/authn.cc
Outdated
| @@ -58,12 +58,14 @@ void Authentication::SaveAuthAttributesToStruct( | |||
| origin.audiences(0)); | |||
| } | |||
| if (!origin.groups().empty()) { | |||
There was a problem hiding this comment.
Can we do it for all claims instead of just "groups"?
There was a problem hiding this comment.
A JWT may contain various claims, including user defined ones (e.g., department, machine-model, IMEI and etc). Probably we can place all claims in a JWT into request.auth.claims[] or we can all non-well-known claims in a JWT into request.auth.claims[]. But such a PR can be a separate PR to keep this PR small and simple.
There was a problem hiding this comment.
In the Pilot PR istio/istio#7747 you just checked in, all claims are matched using ListMatcher. If you don't create ListValue for all claims here, RBAC will break.
There was a problem hiding this comment.
Per discussions, in this PR, JWT claims are extracted as string lists for RBAC list matcher. A new PR https://github.com/istio/proxy/issues/1920 has been created to change the "claims" to a protobuf struct.
e795b7c to
4b603c0
Compare
yangminzhu
left a comment
There was a problem hiding this comment.
I recommend to do #1920 right in this PR.
The code and logic in ProcessJwtPayload() is already complex and seems quite hack to me. It's better to avoid making it more complex and the claims_string_list seems a very specific solution.
dc4e421 to
80fbc16
Compare
ec5ae71 to
7434c90
Compare
| if (field.second.list_value().values_size() > 0) { | ||
| // Only uses the first item in the list as string | ||
| (*entries)[field.first] = | ||
| field.second.list_value().values().Get(0).string_value(); |
There was a problem hiding this comment.
We need to make them comma separated strings. If this is not fixed now, please leave a TODO here.
| "some-other-string-claims": "some-claims-kept" | ||
| }, | ||
| raw_claims: "\n {\n \"iss\": \"issuer@foo.com\",\n \"sub\": \"sub@foo.com\",\n \"aud\": \"aud1\",\n \"non-string-will-be-ignored\": 1512754205,\n \"some-other-string-claims\": \"some-claims-kept\"\n }\n " | ||
| raw_claims: "\n {\n \"iss\": \"issuer@foo.com\",\n \"sub\": \"sub@foo.com\",\n \"aud\": \"aud1\",\n \"non-string-will-be-ignored\": 1512754205,\n \"some-other-string-claims\": \"some-claims-kept\"\n }\n ", |
There was a problem hiding this comment.
In the test case, you may want to have claims that have more than one string entries.
There was a problem hiding this comment.
Done: added a claim of two string entries.
src/envoy/http/authn/authn_utils.cc
Outdated
| void ExtractJwtGroups( | ||
| const Envoy::Json::Object& obj, | ||
| void ExtractStringList( | ||
| const std::string key, const Envoy::Json::Object& obj, |
| payload->mutable_claims(); | ||
|
|
||
| // Extract claims | ||
| // Extract claims as strings |
There was a problem hiding this comment.
Since you are doing it for all claims, do you want to replace the logic here with what you had for ExtractStringList()?
There was a problem hiding this comment.
ExtractStringList() extracts a string list whereas the code here only extracts a string. So the logic for ExtractStringList() is not applied here.
There was a problem hiding this comment.
I mean, you can apply the same logic, first try as a string, then string list, here. With the current way, you actually do it twice, first cast all claims to string in this function, then cast them to string list in ExtractStringList function.
There was a problem hiding this comment.
Before ExtractStringList(key, *json_obj, *claims, list) is called, claims must have been extracted. Hence the separation of two loops (one at line 93, the other at line 123).
|
/retest |
| const std::string& key, const Envoy::Json::Object& obj, | ||
| const ::google::protobuf::Map< ::std::string, ::std::string>& claims, | ||
| istio::authn::JwtPayload* payload) { | ||
| const std::string& key = kJwtGroupsKey; |
There was a problem hiding this comment.
Do you still need kJwtGroupsKey in line 29?
There was a problem hiding this comment.
No, I have removed it. Thanks.
|
This PR is replaced by #1925, which use protobuf::Struct for storing claims. |
|
@lei-tang: PR needs rebase. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
|
This PR is closed as it has been replaced by #1925. |
What this PR does / why we need it: Extract JWT claims as string lists under request.auth.claims[] for RBAC.
Which issue this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)format, will close that issue when PR gets merged): fixes #Special notes for your reviewer:
Release note: