diff --git a/kubernetes/customresourcedefinitions.gen.yaml b/kubernetes/customresourcedefinitions.gen.yaml index b1115f3788a..af5485b1eb3 100644 --- a/kubernetes/customresourcedefinitions.gen.yaml +++ b/kubernetes/customresourcedefinitions.gen.yaml @@ -5570,6 +5570,19 @@ spec: type: string jwksUri: type: string + outputClaimToHeader: + description: This field specifies a list of operations to copy + the claim to HTTP headers on a successfully verified token. + items: + properties: + claim: + description: The name of the claim to be copied from. + type: string + header: + description: The name of the header to be created. + type: string + type: object + type: array outputPayloadToHeader: type: string type: object diff --git a/python/istio_api/security/v1beta1/jwt_pb2.py b/python/istio_api/security/v1beta1/jwt_pb2.py index 54cd22e9744..636bd9b44c2 100644 --- a/python/istio_api/security/v1beta1/jwt_pb2.py +++ b/python/istio_api/security/v1beta1/jwt_pb2.py @@ -21,7 +21,7 @@ package='istio.security.v1beta1', syntax='proto3', serialized_options=_b('Z\035istio.io/api/security/v1beta1'), - serialized_pb=_b('\n\x1asecurity/v1beta1/jwt.proto\x12\x16istio.security.v1beta1\x1a\x1fgoogle/api/field_behavior.proto\"\xca\x02\n\x07JWTRule\x12\x1c\n\x06issuer\x18\x01 \x01(\tB\x04\xe2\x41\x01\x02R\x06issuer\x12\x1c\n\taudiences\x18\x02 \x03(\tR\taudiences\x12\x19\n\x08jwks_uri\x18\x03 \x01(\tR\x07jwksUri\x12\x12\n\x04jwks\x18\n \x01(\tR\x04jwks\x12\x44\n\x0c\x66rom_headers\x18\x06 \x03(\x0b\x32!.istio.security.v1beta1.JWTHeaderR\x0b\x66romHeaders\x12\x1f\n\x0b\x66rom_params\x18\x07 \x03(\tR\nfromParams\x12\x37\n\x18output_payload_to_header\x18\x08 \x01(\tR\x15outputPayloadToHeader\x12\x34\n\x16\x66orward_original_token\x18\t \x01(\x08R\x14\x66orwardOriginalToken\"=\n\tJWTHeader\x12\x18\n\x04name\x18\x01 \x01(\tB\x04\xe2\x41\x01\x02R\x04name\x12\x16\n\x06prefix\x18\x02 \x01(\tR\x06prefixB\x1fZ\x1distio.io/api/security/v1beta1b\x06proto3') + serialized_pb=_b('\n\x1asecurity/v1beta1/jwt.proto\x12\x16istio.security.v1beta1\x1a\x1fgoogle/api/field_behavior.proto\"\xa6\x03\n\x07JWTRule\x12\x1c\n\x06issuer\x18\x01 \x01(\tB\x04\xe2\x41\x01\x02R\x06issuer\x12\x1c\n\taudiences\x18\x02 \x03(\tR\taudiences\x12\x19\n\x08jwks_uri\x18\x03 \x01(\tR\x07jwksUri\x12\x12\n\x04jwks\x18\n \x01(\tR\x04jwks\x12\x44\n\x0c\x66rom_headers\x18\x06 \x03(\x0b\x32!.istio.security.v1beta1.JWTHeaderR\x0b\x66romHeaders\x12\x1f\n\x0b\x66rom_params\x18\x07 \x03(\tR\nfromParams\x12\x37\n\x18output_payload_to_header\x18\x08 \x01(\tR\x15outputPayloadToHeader\x12Z\n\x16output_claim_to_header\x18\x0b \x03(\x0b\x32%.istio.security.v1beta1.ClaimToHeaderR\x13outputClaimToHeader\x12\x34\n\x16\x66orward_original_token\x18\t \x01(\x08R\x14\x66orwardOriginalToken\"=\n\tJWTHeader\x12\x18\n\x04name\x18\x01 \x01(\tB\x04\xe2\x41\x01\x02R\x04name\x12\x16\n\x06prefix\x18\x02 \x01(\tR\x06prefix\"=\n\rClaimToHeader\x12\x16\n\x06header\x18\x01 \x01(\tR\x06header\x12\x14\n\x05\x63laim\x18\x02 \x01(\tR\x05\x63laimB\x1fZ\x1distio.io/api/security/v1beta1b\x06proto3') , dependencies=[google_dot_api_dot_field__behavior__pb2.DESCRIPTOR,]) @@ -85,7 +85,14 @@ is_extension=False, extension_scope=None, serialized_options=None, json_name='outputPayloadToHeader', file=DESCRIPTOR), _descriptor.FieldDescriptor( - name='forward_original_token', full_name='istio.security.v1beta1.JWTRule.forward_original_token', index=7, + name='output_claim_to_header', full_name='istio.security.v1beta1.JWTRule.output_claim_to_header', index=7, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, json_name='outputClaimToHeader', file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='forward_original_token', full_name='istio.security.v1beta1.JWTRule.forward_original_token', index=8, number=9, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, @@ -104,7 +111,7 @@ oneofs=[ ], serialized_start=88, - serialized_end=418, + serialized_end=510, ) @@ -141,13 +148,53 @@ extension_ranges=[], oneofs=[ ], - serialized_start=420, - serialized_end=481, + serialized_start=512, + serialized_end=573, +) + + +_CLAIMTOHEADER = _descriptor.Descriptor( + name='ClaimToHeader', + full_name='istio.security.v1beta1.ClaimToHeader', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='header', full_name='istio.security.v1beta1.ClaimToHeader.header', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, json_name='header', file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='claim', full_name='istio.security.v1beta1.ClaimToHeader.claim', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, json_name='claim', file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=575, + serialized_end=636, ) _JWTRULE.fields_by_name['from_headers'].message_type = _JWTHEADER +_JWTRULE.fields_by_name['output_claim_to_header'].message_type = _CLAIMTOHEADER DESCRIPTOR.message_types_by_name['JWTRule'] = _JWTRULE DESCRIPTOR.message_types_by_name['JWTHeader'] = _JWTHEADER +DESCRIPTOR.message_types_by_name['ClaimToHeader'] = _CLAIMTOHEADER _sym_db.RegisterFileDescriptor(DESCRIPTOR) JWTRule = _reflection.GeneratedProtocolMessageType('JWTRule', (_message.Message,), { @@ -164,6 +211,13 @@ }) _sym_db.RegisterMessage(JWTHeader) +ClaimToHeader = _reflection.GeneratedProtocolMessageType('ClaimToHeader', (_message.Message,), { + 'DESCRIPTOR' : _CLAIMTOHEADER, + '__module__' : 'security.v1beta1.jwt_pb2' + # @@protoc_insertion_point(class_scope:istio.security.v1beta1.ClaimToHeader) + }) +_sym_db.RegisterMessage(ClaimToHeader) + DESCRIPTOR._options = None _JWTRULE.fields_by_name['issuer']._options = None diff --git a/security/v1beta1/jwt.gen.json b/security/v1beta1/jwt.gen.json index 9be783887c4..e48c34d825f 100644 --- a/security/v1beta1/jwt.gen.json +++ b/security/v1beta1/jwt.gen.json @@ -6,6 +6,20 @@ }, "components": { "schemas": { + "istio.security.v1beta1.ClaimToHeader": { + "description": "This message specifies the detail for copying claim to header.", + "type": "object", + "properties": { + "header": { + "description": "The name of the header to be created. The header will be overridden if it already exists in the request.", + "type": "string" + }, + "claim": { + "description": "The name of the claim to be copied from. Only claim of type string is supported. The header will be set to an empty value if the claim does not exist or the type of the claim is not string.", + "type": "string" + } + } + }, "istio.security.v1beta1.JWTHeader": { "description": "This message specifies a header location to extract JWT token.", "type": "object", @@ -61,6 +75,13 @@ "description": "This field specifies the header name to output a successfully verified JWT payload to the backend. The forwarded data is `base64_encoded(jwt_payload_in_JSON)`. If it is not specified, the payload will not be emitted.", "type": "string" }, + "outputClaimToHeader": { + "description": "This field specifies a list of operations to copy the claim to HTTP headers on a successfully verified token. This differs from the `output_payload_to_header` by allowing outputting individual claims instead of the whole payload. The header specified in each operation in the list must be unique. ``` outputClaimToHeader: - header: x-my-company-jwt-group claim: my-group - header: x-test-environment-flag claim: test-flag ```", + "type": "array", + "items": { + "$ref": "#/components/schemas/istio.security.v1beta1.ClaimToHeader" + } + }, "forwardOriginalToken": { "description": "If set to true, the orginal token will be kept for the ustream request. Default is false.", "type": "boolean" diff --git a/security/v1beta1/jwt.pb.go b/security/v1beta1/jwt.pb.go index c93474e8d37..e760e7405ae 100644 --- a/security/v1beta1/jwt.pb.go +++ b/security/v1beta1/jwt.pb.go @@ -111,6 +111,17 @@ type JWTRule struct { // backend. The forwarded data is `base64_encoded(jwt_payload_in_JSON)`. If it is not specified, // the payload will not be emitted. OutputPayloadToHeader string `protobuf:"bytes,8,opt,name=output_payload_to_header,json=outputPayloadToHeader,proto3" json:"output_payload_to_header,omitempty"` + // This field specifies a list of operations to copy the claim to HTTP headers on a successfully verified token. + // This differs from the `output_payload_to_header` by allowing outputting individual claims instead of the whole payload. + // The header specified in each operation in the list must be unique. + // ``` + // outputClaimToHeader: + // - header: x-my-company-jwt-group + // claim: my-group + // - header: x-test-environment-flag + // claim: test-flag + // ``` + OutputClaimToHeader []*ClaimToHeader `protobuf:"bytes,11,rep,name=output_claim_to_header,json=outputClaimToHeader,proto3" json:"output_claim_to_header,omitempty"` // If set to true, the orginal token will be kept for the ustream request. Default is false. ForwardOriginalToken bool `protobuf:"varint,9,opt,name=forward_original_token,json=forwardOriginalToken,proto3" json:"forward_original_token,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` @@ -200,6 +211,13 @@ func (m *JWTRule) GetOutputPayloadToHeader() string { return "" } +func (m *JWTRule) GetOutputClaimToHeader() []*ClaimToHeader { + if m != nil { + return m.OutputClaimToHeader + } + return nil +} + func (m *JWTRule) GetForwardOriginalToken() bool { if m != nil { return m.ForwardOriginalToken @@ -267,39 +285,102 @@ func (m *JWTHeader) GetPrefix() string { return "" } +// This message specifies the detail for copying claim to header. +type ClaimToHeader struct { + // The name of the header to be created. The header will be overridden if it already exists in the request. + Header string `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + // The name of the claim to be copied from. Only claim of type string is supported. + // The header will be set to an empty value if the claim does not exist or the type of the claim is not string. + Claim string `protobuf:"bytes,2,opt,name=claim,proto3" json:"claim,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ClaimToHeader) Reset() { *m = ClaimToHeader{} } +func (m *ClaimToHeader) String() string { return proto.CompactTextString(m) } +func (*ClaimToHeader) ProtoMessage() {} +func (*ClaimToHeader) Descriptor() ([]byte, []int) { + return fileDescriptor_163ab6fd32fb6b15, []int{2} +} +func (m *ClaimToHeader) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClaimToHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ClaimToHeader.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ClaimToHeader) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClaimToHeader.Merge(m, src) +} +func (m *ClaimToHeader) XXX_Size() int { + return m.Size() +} +func (m *ClaimToHeader) XXX_DiscardUnknown() { + xxx_messageInfo_ClaimToHeader.DiscardUnknown(m) +} + +var xxx_messageInfo_ClaimToHeader proto.InternalMessageInfo + +func (m *ClaimToHeader) GetHeader() string { + if m != nil { + return m.Header + } + return "" +} + +func (m *ClaimToHeader) GetClaim() string { + if m != nil { + return m.Claim + } + return "" +} + func init() { proto.RegisterType((*JWTRule)(nil), "istio.security.v1beta1.JWTRule") proto.RegisterType((*JWTHeader)(nil), "istio.security.v1beta1.JWTHeader") + proto.RegisterType((*ClaimToHeader)(nil), "istio.security.v1beta1.ClaimToHeader") } func init() { proto.RegisterFile("security/v1beta1/jwt.proto", fileDescriptor_163ab6fd32fb6b15) } var fileDescriptor_163ab6fd32fb6b15 = []byte{ - // 372 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xc1, 0x4e, 0xea, 0x40, - 0x14, 0x86, 0xd3, 0x42, 0x0a, 0x1d, 0xee, 0x6a, 0x72, 0x2f, 0x99, 0x4b, 0x10, 0x2a, 0xab, 0x26, - 0x26, 0x6d, 0x50, 0x13, 0x57, 0x2e, 0x24, 0x2e, 0x0c, 0x1b, 0x49, 0x53, 0x43, 0xe2, 0x66, 0x32, - 0xd0, 0x29, 0x0c, 0x94, 0x4e, 0x33, 0x33, 0x05, 0x79, 0x43, 0xe3, 0xca, 0x47, 0x30, 0x7d, 0x12, - 0xd3, 0x69, 0xd5, 0x68, 0xdc, 0x9d, 0xf3, 0xfd, 0xe7, 0xb4, 0xff, 0x9c, 0x1f, 0xf4, 0x24, 0x5d, - 0xe6, 0x82, 0xa9, 0xa3, 0xbf, 0x1f, 0x2f, 0xa8, 0x22, 0x63, 0x7f, 0x73, 0x50, 0x5e, 0x26, 0xb8, - 0xe2, 0xb0, 0xcb, 0xa4, 0x62, 0xdc, 0xfb, 0x98, 0xf0, 0xea, 0x89, 0xde, 0x70, 0xc5, 0xf9, 0x2a, - 0xa1, 0x3e, 0xc9, 0x98, 0x1f, 0x33, 0x9a, 0x44, 0x78, 0x41, 0xd7, 0x64, 0xcf, 0xb8, 0xa8, 0x16, - 0x47, 0x2f, 0x26, 0x68, 0x4d, 0xe7, 0x61, 0x90, 0x27, 0x14, 0xf6, 0x81, 0xc5, 0xa4, 0xcc, 0xa9, - 0x40, 0x86, 0x63, 0xb8, 0xf6, 0xa4, 0x59, 0xdc, 0x18, 0x66, 0x50, 0x33, 0xd8, 0x07, 0x36, 0xc9, - 0x23, 0x46, 0xd3, 0x25, 0x95, 0xc8, 0x74, 0x1a, 0xae, 0x1d, 0x7c, 0x01, 0xf8, 0x1f, 0xb4, 0x37, - 0x87, 0xad, 0xc4, 0xb9, 0x60, 0xa8, 0x51, 0x6e, 0x07, 0xad, 0xb2, 0x7f, 0x10, 0x0c, 0x42, 0xd0, - 0x2c, 0x4b, 0x04, 0x34, 0xd6, 0x35, 0xbc, 0x05, 0x7f, 0x62, 0xc1, 0x77, 0x78, 0x4d, 0x49, 0x44, - 0x85, 0x44, 0x96, 0xd3, 0x70, 0x3b, 0xe7, 0xa7, 0xde, 0xef, 0xcf, 0xf0, 0xa6, 0xf3, 0xf0, 0x4e, - 0x4f, 0x06, 0x9d, 0x72, 0xad, 0xaa, 0x25, 0x1c, 0x02, 0xdd, 0xe2, 0x8c, 0x08, 0xb2, 0x93, 0xa8, - 0xa5, 0x4d, 0x81, 0x12, 0xcd, 0x34, 0x81, 0x57, 0x00, 0xf1, 0x5c, 0x65, 0xb9, 0xc2, 0x19, 0x39, - 0x26, 0x9c, 0x44, 0x58, 0xf1, 0xfa, 0x9f, 0xa8, 0xad, 0xed, 0xfc, 0xab, 0xf4, 0x59, 0x25, 0x87, - 0xbc, 0xfa, 0x34, 0xbc, 0x04, 0xdd, 0x98, 0x8b, 0x03, 0x11, 0x11, 0xe6, 0x82, 0xad, 0x58, 0x4a, - 0x12, 0xac, 0xf8, 0x96, 0xa6, 0xc8, 0x76, 0x0c, 0xb7, 0x1d, 0xfc, 0xad, 0xd5, 0xfb, 0x5a, 0x0c, - 0x4b, 0x6d, 0x74, 0x0d, 0xec, 0x4f, 0xa7, 0x10, 0x81, 0x66, 0x4a, 0x76, 0xf4, 0xdb, 0x2d, 0x35, - 0x81, 0x5d, 0x60, 0x65, 0x82, 0xc6, 0xec, 0x09, 0x99, 0xda, 0x43, 0xdd, 0x4d, 0xce, 0x9e, 0x8b, - 0x81, 0xf1, 0x5a, 0x0c, 0x8c, 0xb7, 0x62, 0x60, 0x3c, 0x9e, 0x54, 0xb7, 0x60, 0x5c, 0x87, 0xf7, - 0x33, 0xfb, 0x85, 0xa5, 0xf3, 0xbb, 0x78, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xd0, 0x38, 0x7c, 0xfc, - 0x16, 0x02, 0x00, 0x00, + // 426 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x52, 0xd1, 0x6e, 0xd3, 0x30, + 0x14, 0x95, 0xdb, 0x92, 0x36, 0xb7, 0xf0, 0x62, 0x46, 0x64, 0xa6, 0xd1, 0x95, 0x4a, 0x48, 0x95, + 0x90, 0x12, 0x0d, 0x90, 0x78, 0xda, 0x03, 0x83, 0x07, 0xb4, 0x17, 0xa6, 0x28, 0x68, 0xd2, 0x5e, + 0x2c, 0xb7, 0x71, 0x3a, 0x6f, 0x49, 0x1c, 0xd9, 0xce, 0xca, 0x7e, 0x88, 0x6f, 0xe1, 0x91, 0x4f, + 0x40, 0xf9, 0x12, 0x14, 0xdb, 0x05, 0x8a, 0xe0, 0xed, 0xde, 0x73, 0xcf, 0xb9, 0x39, 0x27, 0xbe, + 0x70, 0xa8, 0xf9, 0xba, 0x55, 0xc2, 0xdc, 0x27, 0x77, 0x27, 0x2b, 0x6e, 0xd8, 0x49, 0x72, 0xb3, + 0x35, 0x71, 0xa3, 0xa4, 0x91, 0x38, 0x12, 0xda, 0x08, 0x19, 0xef, 0x18, 0xb1, 0x67, 0x1c, 0x1e, + 0x6f, 0xa4, 0xdc, 0x94, 0x3c, 0x61, 0x8d, 0x48, 0x0a, 0xc1, 0xcb, 0x9c, 0xae, 0xf8, 0x35, 0xbb, + 0x13, 0x52, 0x39, 0xe1, 0xe2, 0xeb, 0x10, 0xc6, 0xe7, 0x97, 0x59, 0xda, 0x96, 0x1c, 0x1f, 0x41, + 0x20, 0xb4, 0x6e, 0xb9, 0x22, 0x68, 0x8e, 0x96, 0xe1, 0xd9, 0xa8, 0x7b, 0x87, 0x06, 0xa9, 0xc7, + 0xf0, 0x11, 0x84, 0xac, 0xcd, 0x05, 0xaf, 0xd7, 0x5c, 0x93, 0xc1, 0x7c, 0xb8, 0x0c, 0xd3, 0xdf, + 0x00, 0x7e, 0x0a, 0x93, 0x9b, 0xed, 0xad, 0xa6, 0xad, 0x12, 0x64, 0xd8, 0xab, 0xd3, 0x71, 0xdf, + 0x7f, 0x56, 0x02, 0x63, 0x18, 0xf5, 0x25, 0x01, 0x0b, 0xdb, 0x1a, 0x7f, 0x80, 0x87, 0x85, 0x92, + 0x15, 0xbd, 0xe6, 0x2c, 0xe7, 0x4a, 0x93, 0x60, 0x3e, 0x5c, 0x4e, 0x5f, 0x3d, 0x8f, 0xff, 0x1d, + 0x23, 0x3e, 0xbf, 0xcc, 0x3e, 0x5a, 0x66, 0x3a, 0xed, 0x65, 0xae, 0xd6, 0xf8, 0x18, 0x6c, 0x4b, + 0x1b, 0xa6, 0x58, 0xa5, 0xc9, 0xd8, 0x9a, 0x82, 0x1e, 0xba, 0xb0, 0x08, 0x7e, 0x0b, 0x44, 0xb6, + 0xa6, 0x69, 0x0d, 0x6d, 0xd8, 0x7d, 0x29, 0x59, 0x4e, 0x8d, 0xf4, 0xdf, 0x24, 0x13, 0x6b, 0xe7, + 0x89, 0x9b, 0x5f, 0xb8, 0x71, 0x26, 0xdd, 0x6a, 0x7c, 0x05, 0x91, 0x17, 0xae, 0x4b, 0x26, 0xaa, + 0x3f, 0x64, 0x53, 0xeb, 0xf4, 0xc5, 0xff, 0x9c, 0xbe, 0xef, 0xe9, 0xbb, 0x35, 0xe9, 0x63, 0xb7, + 0x64, 0x0f, 0xc4, 0x6f, 0x20, 0x2a, 0xa4, 0xda, 0x32, 0x95, 0x53, 0xa9, 0xc4, 0x46, 0xd4, 0xac, + 0xa4, 0x46, 0xde, 0xf2, 0x9a, 0x84, 0x73, 0xb4, 0x9c, 0xa4, 0x07, 0x7e, 0xfa, 0xc9, 0x0f, 0xb3, + 0x7e, 0xb6, 0x38, 0x85, 0xf0, 0xd7, 0x5f, 0xc0, 0x04, 0x46, 0x35, 0xab, 0xf8, 0xde, 0x3b, 0x59, + 0x04, 0x47, 0x10, 0x34, 0x8a, 0x17, 0xe2, 0x0b, 0x19, 0xd8, 0x7c, 0xbe, 0x5b, 0x9c, 0xc2, 0xa3, + 0x7d, 0x17, 0x11, 0x04, 0x3e, 0x11, 0x72, 0x44, 0xd7, 0xe1, 0x03, 0x78, 0x60, 0x23, 0x7b, 0xbd, + 0x6b, 0xce, 0x5e, 0x7e, 0xeb, 0x66, 0xe8, 0x7b, 0x37, 0x43, 0x3f, 0xba, 0x19, 0xba, 0x7a, 0xe6, + 0xc2, 0x0b, 0x69, 0xef, 0xea, 0xef, 0xb3, 0x5c, 0x05, 0xf6, 0xb4, 0x5e, 0xff, 0x0c, 0x00, 0x00, + 0xff, 0xff, 0xbd, 0x49, 0xe8, 0x33, 0xb1, 0x02, 0x00, 0x00, } func (m *JWTRule) Marshal() (dAtA []byte, err error) { @@ -326,6 +407,20 @@ func (m *JWTRule) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.OutputClaimToHeader) > 0 { + for iNdEx := len(m.OutputClaimToHeader) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.OutputClaimToHeader[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintJwt(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } + } if len(m.Jwks) > 0 { i -= len(m.Jwks) copy(dAtA[i:], m.Jwks) @@ -440,6 +535,47 @@ func (m *JWTHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ClaimToHeader) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ClaimToHeader) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ClaimToHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Claim) > 0 { + i -= len(m.Claim) + copy(dAtA[i:], m.Claim) + i = encodeVarintJwt(dAtA, i, uint64(len(m.Claim))) + i-- + dAtA[i] = 0x12 + } + if len(m.Header) > 0 { + i -= len(m.Header) + copy(dAtA[i:], m.Header) + i = encodeVarintJwt(dAtA, i, uint64(len(m.Header))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintJwt(dAtA []byte, offset int, v uint64) int { offset -= sovJwt(v) base := offset @@ -494,6 +630,12 @@ func (m *JWTRule) Size() (n int) { if l > 0 { n += 1 + l + sovJwt(uint64(l)) } + if len(m.OutputClaimToHeader) > 0 { + for _, e := range m.OutputClaimToHeader { + l = e.Size() + n += 1 + l + sovJwt(uint64(l)) + } + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -520,6 +662,26 @@ func (m *JWTHeader) Size() (n int) { return n } +func (m *ClaimToHeader) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Header) + if l > 0 { + n += 1 + l + sovJwt(uint64(l)) + } + l = len(m.Claim) + if l > 0 { + n += 1 + l + sovJwt(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func sovJwt(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -801,6 +963,40 @@ func (m *JWTRule) Unmarshal(dAtA []byte) error { } m.Jwks = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OutputClaimToHeader", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowJwt + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthJwt + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthJwt + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OutputClaimToHeader = append(m.OutputClaimToHeader, &ClaimToHeader{}) + if err := m.OutputClaimToHeader[len(m.OutputClaimToHeader)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipJwt(dAtA[iNdEx:]) @@ -938,6 +1134,121 @@ func (m *JWTHeader) Unmarshal(dAtA []byte) error { } return nil } +func (m *ClaimToHeader) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowJwt + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClaimToHeader: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClaimToHeader: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowJwt + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthJwt + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthJwt + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Header = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Claim", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowJwt + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthJwt + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthJwt + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Claim = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipJwt(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthJwt + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipJwt(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/security/v1beta1/jwt.pb.html b/security/v1beta1/jwt.pb.html index 19f97052807..969c81f0313 100644 --- a/security/v1beta1/jwt.pb.html +++ b/security/v1beta1/jwt.pb.html @@ -6,7 +6,7 @@ generator: protoc-gen-docs schema: istio.security.v1beta1.JWTRule aliases: [/docs/reference/config/security/v1beta1/jwt] -number_of_entries: 2 +number_of_entries: 3 ---

JWTRule

@@ -163,6 +163,26 @@

JWTRule

backend. The forwarded data is base64_encoded(jwt_payload_in_JSON). If it is not specified, the payload will not be emitted.

+ + +No + + + +outputClaimToHeader +ClaimToHeader[] + +

This field specifies a list of operations to copy the claim to HTTP headers on a successfully verified token. +This differs from the output_payload_to_header by allowing outputting individual claims instead of the whole payload. +The header specified in each operation in the list must be unique.

+ +
  outputClaimToHeader:
+  - header: x-my-company-jwt-group
+    claim: my-group
+  - header: x-test-environment-flag
+    claim: test-flag
+
+ No @@ -223,3 +243,43 @@

JWTHeader

+

ClaimToHeader

+
+

This message specifies the detail for copying claim to header.

+ + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescriptionRequired
headerstring +

The name of the header to be created. The header will be overridden if it already exists in the request.

+ +
+No +
claimstring +

The name of the claim to be copied from. Only claim of type string is supported. +The header will be set to an empty value if the claim does not exist or the type of the claim is not string.

+ +
+No +
+
diff --git a/security/v1beta1/jwt.proto b/security/v1beta1/jwt.proto index f0578235978..709b40a7026 100644 --- a/security/v1beta1/jwt.proto +++ b/security/v1beta1/jwt.proto @@ -133,6 +133,18 @@ message JWTRule { // the payload will not be emitted. string output_payload_to_header = 8; + // This field specifies a list of operations to copy the claim to HTTP headers on a successfully verified token. + // This differs from the `output_payload_to_header` by allowing outputting individual claims instead of the whole payload. + // The header specified in each operation in the list must be unique. + // ``` + // outputClaimToHeader: + // - header: x-my-company-jwt-group + // claim: my-group + // - header: x-test-environment-flag + // claim: test-flag + // ``` + repeated ClaimToHeader output_claim_to_header = 11; + // If set to true, the orginal token will be kept for the ustream request. Default is false. bool forward_original_token = 9; } @@ -147,3 +159,13 @@ message JWTHeader { // If the header doesn't have this exact prefix, it is considerred invalid. string prefix = 2; } + +// This message specifies the detail for copying claim to header. +message ClaimToHeader { + // The name of the header to be created. The header will be overridden if it already exists in the request. + string header = 1; + + // The name of the claim to be copied from. Only claim of type string is supported. + // The header will be set to an empty value if the claim does not exist or the type of the claim is not string. + string claim = 2; +} diff --git a/security/v1beta1/jwt_deepcopy.gen.go b/security/v1beta1/jwt_deepcopy.gen.go index c1bc0d380d9..91283c861be 100644 --- a/security/v1beta1/jwt_deepcopy.gen.go +++ b/security/v1beta1/jwt_deepcopy.gen.go @@ -56,3 +56,24 @@ func (in *JWTHeader) DeepCopy() *JWTHeader { func (in *JWTHeader) DeepCopyInterface() interface{} { return in.DeepCopy() } + +// DeepCopyInto supports using ClaimToHeader within kubernetes types, where deepcopy-gen is used. +func (in *ClaimToHeader) DeepCopyInto(out *ClaimToHeader) { + p := proto.Clone(in).(*ClaimToHeader) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClaimToHeader. Required by controller-gen. +func (in *ClaimToHeader) DeepCopy() *ClaimToHeader { + if in == nil { + return nil + } + out := new(ClaimToHeader) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new ClaimToHeader. Required by controller-gen. +func (in *ClaimToHeader) DeepCopyInterface() interface{} { + return in.DeepCopy() +} diff --git a/security/v1beta1/jwt_json.gen.go b/security/v1beta1/jwt_json.gen.go index 2a681533bd9..b499e44250f 100644 --- a/security/v1beta1/jwt_json.gen.go +++ b/security/v1beta1/jwt_json.gen.go @@ -39,6 +39,17 @@ func (this *JWTHeader) UnmarshalJSON(b []byte) error { return JwtUnmarshaler.Unmarshal(bytes.NewReader(b), this) } +// MarshalJSON is a custom marshaler for ClaimToHeader +func (this *ClaimToHeader) MarshalJSON() ([]byte, error) { + str, err := JwtMarshaler.MarshalToString(this) + return []byte(str), err +} + +// UnmarshalJSON is a custom unmarshaler for ClaimToHeader +func (this *ClaimToHeader) UnmarshalJSON(b []byte) error { + return JwtUnmarshaler.Unmarshal(bytes.NewReader(b), this) +} + var ( JwtMarshaler = &github_com_gogo_protobuf_jsonpb.Marshaler{} JwtUnmarshaler = &github_com_gogo_protobuf_jsonpb.Unmarshaler{AllowUnknownFields: true} diff --git a/security/v1beta1/request_authentication.gen.json b/security/v1beta1/request_authentication.gen.json index 7536e918854..7c9859c0e6b 100644 --- a/security/v1beta1/request_authentication.gen.json +++ b/security/v1beta1/request_authentication.gen.json @@ -6,6 +6,20 @@ }, "components": { "schemas": { + "istio.security.v1beta1.ClaimToHeader": { + "description": "This message specifies the detail for copying claim to header.", + "type": "object", + "properties": { + "header": { + "description": "The name of the header to be created. The header will be overridden if it already exists in the request.", + "type": "string" + }, + "claim": { + "description": "The name of the claim to be copied from. Only claim of type string is supported. The header will be set to an empty value if the claim does not exist or the type of the claim is not string.", + "type": "string" + } + } + }, "istio.security.v1beta1.JWTHeader": { "description": "This message specifies a header location to extract JWT token.", "type": "object", @@ -61,6 +75,13 @@ "description": "This field specifies the header name to output a successfully verified JWT payload to the backend. The forwarded data is `base64_encoded(jwt_payload_in_JSON)`. If it is not specified, the payload will not be emitted.", "type": "string" }, + "outputClaimToHeader": { + "description": "This field specifies a list of operations to copy the claim to HTTP headers on a successfully verified token. This differs from the `output_payload_to_header` by allowing outputting individual claims instead of the whole payload. The header specified in each operation in the list must be unique. ``` outputClaimToHeader: - header: x-my-company-jwt-group claim: my-group - header: x-test-environment-flag claim: test-flag ```", + "type": "array", + "items": { + "$ref": "#/components/schemas/istio.security.v1beta1.ClaimToHeader" + } + }, "forwardOriginalToken": { "description": "If set to true, the orginal token will be kept for the ustream request. Default is false.", "type": "boolean"