mirror of
https://github.com/pomerium/pomerium.git
synced 2025-07-14 23:38:39 +02:00
Add new jwt issuer format route option (#5338)
This commit is contained in:
parent
9e9ed8853f
commit
a42e286637
5 changed files with 831 additions and 680 deletions
|
@ -32,7 +32,18 @@ type HeadersRequest struct {
|
||||||
// NewHeadersRequestFromPolicy creates a new HeadersRequest from a policy.
|
// NewHeadersRequestFromPolicy creates a new HeadersRequest from a policy.
|
||||||
func NewHeadersRequestFromPolicy(policy *config.Policy, http RequestHTTP) (*HeadersRequest, error) {
|
func NewHeadersRequestFromPolicy(policy *config.Policy, http RequestHTTP) (*HeadersRequest, error) {
|
||||||
input := new(HeadersRequest)
|
input := new(HeadersRequest)
|
||||||
|
var issuerFormat string
|
||||||
|
if policy != nil {
|
||||||
|
issuerFormat = policy.JWTIssuerFormat
|
||||||
|
}
|
||||||
|
switch issuerFormat {
|
||||||
|
case "", "hostOnly":
|
||||||
input.Issuer = http.Hostname
|
input.Issuer = http.Hostname
|
||||||
|
case "uri":
|
||||||
|
input.Issuer = fmt.Sprintf("https://%s/", http.Hostname)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid issuer format: %q", policy.JWTIssuerFormat)
|
||||||
|
}
|
||||||
if policy != nil {
|
if policy != nil {
|
||||||
input.EnableGoogleCloudServerlessAuthentication = policy.EnableGoogleCloudServerlessAuthentication
|
input.EnableGoogleCloudServerlessAuthentication = policy.EnableGoogleCloudServerlessAuthentication
|
||||||
input.EnableRoutingKey = policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_RING_HASH ||
|
input.EnableRoutingKey = policy.EnvoyOpts.GetLbPolicy() == envoy_config_cluster_v3.Cluster_RING_HASH ||
|
||||||
|
|
|
@ -53,6 +53,48 @@ func TestNewHeadersRequestFromPolicy(t *testing.T) {
|
||||||
}, req)
|
}, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewHeadersRequestFromPolicy_IssuerFormat(t *testing.T) {
|
||||||
|
policy := &config.Policy{
|
||||||
|
EnableGoogleCloudServerlessAuthentication: true,
|
||||||
|
From: "https://*.example.com",
|
||||||
|
To: config.WeightedURLs{
|
||||||
|
{
|
||||||
|
URL: *mustParseURL("http://to.example.com"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range []struct {
|
||||||
|
format string
|
||||||
|
expected string
|
||||||
|
err string
|
||||||
|
}{
|
||||||
|
{format: "", expected: "from.example.com"},
|
||||||
|
{format: "hostOnly", expected: "from.example.com"},
|
||||||
|
{format: "uri", expected: "https://from.example.com/"},
|
||||||
|
{format: "foo", err: `invalid issuer format: "foo"`},
|
||||||
|
} {
|
||||||
|
policy.JWTIssuerFormat = tc.format
|
||||||
|
req, err := NewHeadersRequestFromPolicy(policy, RequestHTTP{
|
||||||
|
Hostname: "from.example.com",
|
||||||
|
ClientCertificate: ClientCertificateInfo{
|
||||||
|
Leaf: "--- FAKE CERTIFICATE ---",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if tc.err != "" {
|
||||||
|
assert.ErrorContains(t, err, tc.err)
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, &HeadersRequest{
|
||||||
|
EnableGoogleCloudServerlessAuthentication: true,
|
||||||
|
Issuer: tc.expected,
|
||||||
|
ToAudience: "https://to.example.com",
|
||||||
|
ClientCertificate: ClientCertificateInfo{
|
||||||
|
Leaf: "--- FAKE CERTIFICATE ---",
|
||||||
|
},
|
||||||
|
}, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewHeadersRequestFromPolicy_nil(t *testing.T) {
|
func TestNewHeadersRequestFromPolicy_nil(t *testing.T) {
|
||||||
req, _ := NewHeadersRequestFromPolicy(nil, RequestHTTP{Hostname: "from.example.com"})
|
req, _ := NewHeadersRequestFromPolicy(nil, RequestHTTP{Hostname: "from.example.com"})
|
||||||
assert.Equal(t, &HeadersRequest{
|
assert.Equal(t, &HeadersRequest{
|
||||||
|
|
|
@ -157,6 +157,12 @@ type Policy struct {
|
||||||
// to upstream requests.
|
// to upstream requests.
|
||||||
EnableGoogleCloudServerlessAuthentication bool `mapstructure:"enable_google_cloud_serverless_authentication" yaml:"enable_google_cloud_serverless_authentication,omitempty"`
|
EnableGoogleCloudServerlessAuthentication bool `mapstructure:"enable_google_cloud_serverless_authentication" yaml:"enable_google_cloud_serverless_authentication,omitempty"`
|
||||||
|
|
||||||
|
// JWTIssuerFormat controls the format of the 'iss' claim in JWTs passed to upstream services by this route.
|
||||||
|
// Possible values:
|
||||||
|
// - "hostOnly" (default): Issuer strings will be the hostname of the route, with no scheme or trailing slash.
|
||||||
|
// - "uri": Issuer strings will be a complete URI, including the scheme and ending with a trailing slash.
|
||||||
|
JWTIssuerFormat string `mapstructure:"jwt_issuer_format" yaml:"jwt_issuer_format,omitempty"`
|
||||||
|
|
||||||
SubPolicies []SubPolicy `mapstructure:"sub_policies" yaml:"sub_policies,omitempty" json:"sub_policies,omitempty"`
|
SubPolicies []SubPolicy `mapstructure:"sub_policies" yaml:"sub_policies,omitempty" json:"sub_policies,omitempty"`
|
||||||
|
|
||||||
EnvoyOpts *envoy_config_cluster_v3.Cluster `mapstructure:"_envoy_opts" yaml:"-" json:"-"`
|
EnvoyOpts *envoy_config_cluster_v3.Cluster `mapstructure:"_envoy_opts" yaml:"-" json:"-"`
|
||||||
|
@ -321,6 +327,13 @@ func NewPolicyFromProto(pb *configpb.Route) (*Policy, error) {
|
||||||
p.EnvoyOpts.Name = pb.Name
|
p.EnvoyOpts.Name = pb.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch pb.GetJwtIssuerFormat() {
|
||||||
|
case configpb.IssuerFormat_IssuerHostOnly:
|
||||||
|
p.JWTIssuerFormat = "hostOnly"
|
||||||
|
case configpb.IssuerFormat_IssuerURI:
|
||||||
|
p.JWTIssuerFormat = "uri"
|
||||||
|
}
|
||||||
|
|
||||||
for _, rwh := range pb.RewriteResponseHeaders {
|
for _, rwh := range pb.RewriteResponseHeaders {
|
||||||
p.RewriteResponseHeaders = append(p.RewriteResponseHeaders, RewriteHeader{
|
p.RewriteResponseHeaders = append(p.RewriteResponseHeaders, RewriteHeader{
|
||||||
Header: rwh.GetHeader(),
|
Header: rwh.GetHeader(),
|
||||||
|
@ -461,6 +474,13 @@ func (p *Policy) ToProto() (*configpb.Route, error) {
|
||||||
pb.LoadBalancingWeights = weights
|
pb.LoadBalancingWeights = weights
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch p.JWTIssuerFormat {
|
||||||
|
case "", "hostOnly":
|
||||||
|
pb.JwtIssuerFormat = configpb.IssuerFormat_IssuerHostOnly
|
||||||
|
case "uri":
|
||||||
|
pb.JwtIssuerFormat = configpb.IssuerFormat_IssuerURI
|
||||||
|
}
|
||||||
|
|
||||||
for _, rwh := range p.RewriteResponseHeaders {
|
for _, rwh := range p.RewriteResponseHeaders {
|
||||||
pb.RewriteResponseHeaders = append(pb.RewriteResponseHeaders, &configpb.RouteRewriteHeader{
|
pb.RewriteResponseHeaders = append(pb.RewriteResponseHeaders, &configpb.RouteRewriteHeader{
|
||||||
Header: rwh.Header,
|
Header: rwh.Header,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -38,7 +38,16 @@ message RouteDirectResponse {
|
||||||
string body = 2;
|
string body = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next ID: 65.
|
enum IssuerFormat {
|
||||||
|
// Issuer strings will be the hostname of the route, with no scheme or
|
||||||
|
// trailing slash.
|
||||||
|
IssuerHostOnly = 0;
|
||||||
|
// Issuer strings will be a complete URI, including the scheme and ending
|
||||||
|
// with a trailing slash.
|
||||||
|
IssuerURI = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next ID: 66.
|
||||||
message Route {
|
message Route {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
|
|
||||||
|
@ -105,6 +114,7 @@ message Route {
|
||||||
string kubernetes_service_account_token = 26;
|
string kubernetes_service_account_token = 26;
|
||||||
string kubernetes_service_account_token_file = 64;
|
string kubernetes_service_account_token_file = 64;
|
||||||
bool enable_google_cloud_serverless_authentication = 42;
|
bool enable_google_cloud_serverless_authentication = 42;
|
||||||
|
IssuerFormat jwt_issuer_format = 65;
|
||||||
|
|
||||||
envoy.config.cluster.v3.Cluster envoy_opts = 36;
|
envoy.config.cluster.v3.Cluster envoy_opts = 36;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue