Skip to content

Commit 8964995

Browse files
committed
add more route options
1 parent 5d3bbae commit 8964995

File tree

4 files changed

+471
-42
lines changed

4 files changed

+471
-42
lines changed

example/main.tf

+35
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,41 @@ resource "pomerium_route" "kubernetes_route" {
203203
tls_upstream_allow_renegotiation = true
204204
}
205205

206+
resource "pomerium_route" "advanced_route" {
207+
name = "advanced-route"
208+
from = "https://advanced.corp.example.com"
209+
to = ["https://internal-service.example.com"]
210+
namespace_id = pomerium_namespace.test_namespace.id
211+
212+
# Response header manipulation
213+
rewrite_response_headers = [
214+
{
215+
header = "Location"
216+
prefix = "http://internal"
217+
value = "https://external"
218+
},
219+
{
220+
header = "Content-Security-Policy"
221+
value = "default-src 'self'"
222+
}
223+
]
224+
set_response_headers = {
225+
"Strict-Transport-Security" = "max-age=31536000"
226+
"X-Frame-Options" = "DENY"
227+
}
228+
229+
tls_custom_ca_key_pair_id = pomerium_key_pair.test_key_pair.id
230+
tls_skip_verify = false
231+
232+
enable_google_cloud_serverless_authentication = true
233+
kubernetes_service_account_token_file = "/path/to/token"
234+
235+
description = "Advanced route with security headers"
236+
logo_url = "https://example.com/logo.png"
237+
238+
show_error_details = true
239+
}
240+
206241
# Data source examples
207242
data "pomerium_namespaces" "all_namespaces" {}
208243

internal/provider/route.go

+66
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66

77
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
8+
"github.com/hashicorp/terraform-plugin-framework/attr"
89
"github.com/hashicorp/terraform-plugin-framework/path"
910
"github.com/hashicorp/terraform-plugin-framework/resource"
1011
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
@@ -199,6 +200,71 @@ func (r *RouteResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
199200
Computed: true,
200201
},
201202
"jwt_groups_filter": JWTGroupsFilterSchema,
203+
"jwt_issuer_format": schema.ObjectAttribute{
204+
Description: "JWT issuer format configuration.",
205+
Optional: true,
206+
AttributeTypes: map[string]attr.Type{
207+
"format": types.StringType,
208+
},
209+
},
210+
"rewrite_response_headers": schema.SetNestedAttribute{
211+
Description: "Response header rewrite rules.",
212+
Optional: true,
213+
NestedObject: schema.NestedAttributeObject{
214+
Attributes: map[string]schema.Attribute{
215+
"header": schema.StringAttribute{
216+
Required: true,
217+
Description: "Header name to rewrite",
218+
},
219+
"prefix": schema.StringAttribute{
220+
Optional: true,
221+
Description: "Prefix matcher for the header",
222+
},
223+
"value": schema.StringAttribute{
224+
Required: true,
225+
Description: "New value for the header",
226+
},
227+
},
228+
},
229+
},
230+
"tls_custom_ca_key_pair_id": schema.StringAttribute{
231+
Description: "Custom CA key pair ID for TLS verification.",
232+
Optional: true,
233+
},
234+
"tls_client_key_pair_id": schema.StringAttribute{
235+
Description: "Client key pair ID for TLS client authentication.",
236+
Optional: true,
237+
},
238+
"description": schema.StringAttribute{
239+
Description: "Description of the route.",
240+
Optional: true,
241+
},
242+
"kubernetes_service_account_token_file": schema.StringAttribute{
243+
Description: "Path to the Kubernetes service account token file.",
244+
Optional: true,
245+
},
246+
"logo_url": schema.StringAttribute{
247+
Description: "URL to the logo image.",
248+
Optional: true,
249+
},
250+
"enable_google_cloud_serverless_authentication": schema.BoolAttribute{
251+
Description: "Enable Google Cloud serverless authentication.",
252+
Optional: true,
253+
},
254+
"redirect": schema.ObjectAttribute{
255+
Description: "Redirect configuration.",
256+
Optional: true,
257+
AttributeTypes: map[string]attr.Type{
258+
"host_redirect": types.StringType,
259+
"https_redirect": types.BoolType,
260+
"path_redirect": types.StringType,
261+
"prefix_rewrite": types.StringType,
262+
"response_code": types.Int64Type,
263+
"strip_query": types.BoolType,
264+
"scheme_redirect": types.StringType,
265+
"port_redirect": types.Int64Type,
266+
},
267+
},
202268
},
203269
}
204270
}

internal/provider/route_model.go

+133-42
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,124 @@ import (
44
"context"
55

66
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
7+
"github.com/hashicorp/terraform-plugin-framework/attr"
78
"github.com/hashicorp/terraform-plugin-framework/diag"
89
"github.com/hashicorp/terraform-plugin-framework/types"
910
"github.com/pomerium/enterprise-client-go/pb"
1011
)
1112

1213
// RouteModel represents the shared model for route resources and data sources
1314
type RouteModel struct {
14-
ID types.String `tfsdk:"id"`
15-
Name types.String `tfsdk:"name"`
16-
From types.String `tfsdk:"from"`
17-
To types.Set `tfsdk:"to"`
18-
NamespaceID types.String `tfsdk:"namespace_id"`
19-
Policies types.Set `tfsdk:"policies"`
20-
StatName types.String `tfsdk:"stat_name"`
21-
Prefix types.String `tfsdk:"prefix"`
22-
Path types.String `tfsdk:"path"`
23-
Regex types.String `tfsdk:"regex"`
24-
PrefixRewrite types.String `tfsdk:"prefix_rewrite"`
25-
RegexRewritePattern types.String `tfsdk:"regex_rewrite_pattern"`
26-
RegexRewriteSubstitution types.String `tfsdk:"regex_rewrite_substitution"`
27-
HostRewrite types.String `tfsdk:"host_rewrite"`
28-
HostRewriteHeader types.String `tfsdk:"host_rewrite_header"`
29-
HostPathRegexRewritePattern types.String `tfsdk:"host_path_regex_rewrite_pattern"`
30-
HostPathRegexRewriteSubstitution types.String `tfsdk:"host_path_regex_rewrite_substitution"`
31-
RegexPriorityOrder types.Int64 `tfsdk:"regex_priority_order"`
32-
Timeout timetypes.GoDuration `tfsdk:"timeout"`
33-
IdleTimeout timetypes.GoDuration `tfsdk:"idle_timeout"`
34-
AllowWebsockets types.Bool `tfsdk:"allow_websockets"`
35-
AllowSPDY types.Bool `tfsdk:"allow_spdy"`
36-
TLSSkipVerify types.Bool `tfsdk:"tls_skip_verify"`
37-
TLSUpstreamServerName types.String `tfsdk:"tls_upstream_server_name"`
38-
TLSDownstreamServerName types.String `tfsdk:"tls_downstream_server_name"`
39-
TLSUpstreamAllowRenegotiation types.Bool `tfsdk:"tls_upstream_allow_renegotiation"`
40-
SetRequestHeaders types.Map `tfsdk:"set_request_headers"`
41-
RemoveRequestHeaders types.Set `tfsdk:"remove_request_headers"`
42-
SetResponseHeaders types.Map `tfsdk:"set_response_headers"`
43-
PreserveHostHeader types.Bool `tfsdk:"preserve_host_header"`
44-
PassIdentityHeaders types.Bool `tfsdk:"pass_identity_headers"`
45-
KubernetesServiceAccountToken types.String `tfsdk:"kubernetes_service_account_token"`
46-
IDPClientID types.String `tfsdk:"idp_client_id"`
47-
IDPClientSecret types.String `tfsdk:"idp_client_secret"`
48-
ShowErrorDetails types.Bool `tfsdk:"show_error_details"`
49-
JWTGroupsFilter types.Object `tfsdk:"jwt_groups_filter"`
15+
AllowSPDY types.Bool `tfsdk:"allow_spdy"`
16+
AllowWebsockets types.Bool `tfsdk:"allow_websockets"`
17+
Description types.String `tfsdk:"description"`
18+
EnableGoogleCloudServerlessAuthentication types.Bool `tfsdk:"enable_google_cloud_serverless_authentication"`
19+
From types.String `tfsdk:"from"`
20+
HostPathRegexRewritePattern types.String `tfsdk:"host_path_regex_rewrite_pattern"`
21+
HostPathRegexRewriteSubstitution types.String `tfsdk:"host_path_regex_rewrite_substitution"`
22+
HostRewrite types.String `tfsdk:"host_rewrite"`
23+
HostRewriteHeader types.String `tfsdk:"host_rewrite_header"`
24+
ID types.String `tfsdk:"id"`
25+
IdleTimeout timetypes.GoDuration `tfsdk:"idle_timeout"`
26+
IDPClientID types.String `tfsdk:"idp_client_id"`
27+
IDPClientSecret types.String `tfsdk:"idp_client_secret"`
28+
JWTGroupsFilter types.Object `tfsdk:"jwt_groups_filter"`
29+
JWTIssuerFormat types.Object `tfsdk:"jwt_issuer_format"`
30+
KubernetesServiceAccountToken types.String `tfsdk:"kubernetes_service_account_token"`
31+
KubernetesServiceAccountTokenFile types.String `tfsdk:"kubernetes_service_account_token_file"`
32+
LogoURL types.String `tfsdk:"logo_url"`
33+
Name types.String `tfsdk:"name"`
34+
NamespaceID types.String `tfsdk:"namespace_id"`
35+
PassIdentityHeaders types.Bool `tfsdk:"pass_identity_headers"`
36+
Path types.String `tfsdk:"path"`
37+
Policies types.Set `tfsdk:"policies"`
38+
Prefix types.String `tfsdk:"prefix"`
39+
PrefixRewrite types.String `tfsdk:"prefix_rewrite"`
40+
PreserveHostHeader types.Bool `tfsdk:"preserve_host_header"`
41+
Redirect types.Object `tfsdk:"redirect"`
42+
Regex types.String `tfsdk:"regex"`
43+
RegexPriorityOrder types.Int64 `tfsdk:"regex_priority_order"`
44+
RegexRewritePattern types.String `tfsdk:"regex_rewrite_pattern"`
45+
RegexRewriteSubstitution types.String `tfsdk:"regex_rewrite_substitution"`
46+
RemoveRequestHeaders types.Set `tfsdk:"remove_request_headers"`
47+
RewriteResponseHeaders types.Set `tfsdk:"rewrite_response_headers"`
48+
SetRequestHeaders types.Map `tfsdk:"set_request_headers"`
49+
SetResponseHeaders types.Map `tfsdk:"set_response_headers"`
50+
ShowErrorDetails types.Bool `tfsdk:"show_error_details"`
51+
StatName types.String `tfsdk:"stat_name"`
52+
Timeout timetypes.GoDuration `tfsdk:"timeout"`
53+
TLSClientKeyPairID types.String `tfsdk:"tls_client_key_pair_id"`
54+
TLSCustomCAKeyPairID types.String `tfsdk:"tls_custom_ca_key_pair_id"`
55+
TLSDownstreamServerName types.String `tfsdk:"tls_downstream_server_name"`
56+
TLSSkipVerify types.Bool `tfsdk:"tls_skip_verify"`
57+
TLSUpstreamAllowRenegotiation types.Bool `tfsdk:"tls_upstream_allow_renegotiation"`
58+
TLSUpstreamServerName types.String `tfsdk:"tls_upstream_server_name"`
59+
To types.Set `tfsdk:"to"`
60+
}
61+
62+
var rewriteHeaderAttrTypes = map[string]attr.Type{
63+
"header": types.StringType,
64+
"value": types.StringType,
65+
"prefix": types.StringType,
66+
}
67+
68+
// RewriteHeaderAttrTypes returns the attribute type map for rewrite headers
69+
func RewriteHeaderAttrTypes() map[string]attr.Type {
70+
return rewriteHeaderAttrTypes
71+
}
72+
73+
func rewriteHeadersToPB(src types.Set) []*pb.RouteRewriteHeader {
74+
if (src).IsNull() {
75+
return nil
76+
}
77+
78+
headers := make([]*pb.RouteRewriteHeader, 0)
79+
elements := src.Elements()
80+
for _, element := range elements {
81+
obj := element.(types.Object)
82+
prefixAttr := obj.Attributes()["prefix"].(types.String)
83+
84+
header := &pb.RouteRewriteHeader{
85+
Header: obj.Attributes()["header"].(types.String).ValueString(),
86+
Value: obj.Attributes()["value"].(types.String).ValueString(),
87+
}
88+
89+
if !prefixAttr.IsNull() && prefixAttr.ValueString() != "" {
90+
header.Matcher = &pb.RouteRewriteHeader_Prefix{Prefix: prefixAttr.ValueString()}
91+
}
92+
93+
headers = append(headers, header)
94+
}
95+
return headers
96+
}
97+
98+
func rewriteHeadersFromPB(headers []*pb.RouteRewriteHeader) types.Set {
99+
if len(headers) == 0 {
100+
return types.SetNull(RewriteHeaderObjectType())
101+
}
102+
103+
elements := make([]attr.Value, 0, len(headers))
104+
for _, header := range headers {
105+
prefix := header.GetPrefix()
106+
prefixValue := types.StringNull()
107+
if prefix != "" {
108+
prefixValue = types.StringValue(prefix)
109+
}
110+
111+
attrs := map[string]attr.Value{
112+
"header": types.StringValue(header.Header),
113+
"value": types.StringValue(header.Value),
114+
"prefix": prefixValue,
115+
}
116+
obj, _ := types.ObjectValue(rewriteHeaderAttrTypes, attrs)
117+
elements = append(elements, obj)
118+
}
119+
result, _ := types.SetValue(RewriteHeaderObjectType(), elements)
120+
return result
121+
}
122+
123+
func RewriteHeaderObjectType() attr.Type {
124+
return types.ObjectType{AttrTypes: rewriteHeaderAttrTypes}
50125
}
51126

52127
func ConvertRouteToPB(
@@ -90,14 +165,19 @@ func ConvertRouteToPB(
90165
pbRoute.IdpClientSecret = src.IDPClientSecret.ValueStringPointer()
91166
pbRoute.ShowErrorDetails = src.ShowErrorDetails.ValueBool()
92167
JWTGroupsFilterToPB(ctx, &pbRoute.JwtGroupsFilter, src.JWTGroupsFilter, &diagnostics)
168+
ToStringSliceFromSet(ctx, &pbRoute.To, src.To, &diagnostics)
169+
ToStringSliceFromSet(ctx, &pbRoute.PolicyIds, src.Policies, &diagnostics)
170+
pbRoute.TlsClientKeyPairId = src.TLSClientKeyPairID.ValueStringPointer()
171+
pbRoute.TlsCustomCaKeyPairId = src.TLSCustomCAKeyPairID.ValueStringPointer()
172+
pbRoute.Description = src.Description.ValueStringPointer()
173+
pbRoute.LogoUrl = src.LogoURL.ValueStringPointer()
174+
if !src.EnableGoogleCloudServerlessAuthentication.IsNull() {
175+
pbRoute.EnableGoogleCloudServerlessAuthentication = src.EnableGoogleCloudServerlessAuthentication.ValueBool()
176+
}
177+
pbRoute.KubernetesServiceAccountTokenFile = src.KubernetesServiceAccountTokenFile.ValueStringPointer()
93178

94-
diags := src.To.ElementsAs(ctx, &pbRoute.To, false)
95-
diagnostics.Append(diags...)
179+
pbRoute.RewriteResponseHeaders = rewriteHeadersToPB(src.RewriteResponseHeaders)
96180

97-
if !src.Policies.IsNull() {
98-
diags = src.Policies.ElementsAs(ctx, &pbRoute.PolicyIds, false)
99-
diagnostics.Append(diags...)
100-
}
101181
return pbRoute, diagnostics
102182
}
103183

@@ -143,6 +223,17 @@ func ConvertRouteFromPB(
143223
dst.IDPClientSecret = types.StringPointerValue(src.IdpClientSecret)
144224
dst.ShowErrorDetails = types.BoolValue(src.ShowErrorDetails)
145225
JWTGroupsFilterFromPB(&dst.JWTGroupsFilter, src.JwtGroupsFilter)
226+
dst.TLSClientKeyPairID = types.StringPointerValue(src.TlsClientKeyPairId)
227+
dst.TLSCustomCAKeyPairID = types.StringPointerValue(src.TlsCustomCaKeyPairId)
228+
dst.Description = types.StringPointerValue(src.Description)
229+
dst.LogoURL = types.StringPointerValue(src.LogoUrl)
230+
dst.EnableGoogleCloudServerlessAuthentication = types.BoolNull()
231+
if src.EnableGoogleCloudServerlessAuthentication {
232+
dst.EnableGoogleCloudServerlessAuthentication = types.BoolValue(true)
233+
}
234+
dst.KubernetesServiceAccountTokenFile = types.StringPointerValue(src.KubernetesServiceAccountTokenFile)
235+
236+
dst.RewriteResponseHeaders = rewriteHeadersFromPB(src.RewriteResponseHeaders)
146237

147238
return diagnostics
148239
}

0 commit comments

Comments
 (0)