config: add branding settings (#3558)

This commit is contained in:
Caleb Doxsey 2022-08-16 14:51:47 -06:00 committed by GitHub
parent c9421ec146
commit 46703b9419
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 156 additions and 13 deletions

View file

@ -568,6 +568,8 @@ func (a *Authenticate) getUserInfoData(r *http.Request) (handlers.UserInfoData,
WebAuthnCreationOptions: creationOptions,
WebAuthnRequestOptions: requestOptions,
WebAuthnURL: urlutil.WebAuthnURL(r, authenticateURL, state.sharedKey, r.URL.Query()),
BrandingOptions: a.options.Load().BrandingOptions,
}, nil
}

View file

@ -26,11 +26,13 @@ type UserInfoData struct {
WebAuthnCreationOptions *webauthn.PublicKeyCredentialCreationOptions
WebAuthnRequestOptions *webauthn.PublicKeyCredentialRequestOptions
WebAuthnURL string
BrandingOptions httputil.BrandingOptions
}
// ToJSON converts the data into a JSON map.
func (data UserInfoData) ToJSON() map[string]interface{} {
m := map[string]interface{}{}
func (data UserInfoData) ToJSON() map[string]any {
m := map[string]any{}
m["csrfToken"] = data.CSRFToken
var directoryGroups []json.RawMessage
for _, directoryGroup := range data.DirectoryGroups {
@ -52,6 +54,7 @@ func (data UserInfoData) ToJSON() map[string]interface{} {
m["webAuthnCreationOptions"] = data.WebAuthnCreationOptions
m["webAuthnRequestOptions"] = data.WebAuthnRequestOptions
m["webAuthnUrl"] = data.WebAuthnURL
httputil.AddBrandingOptionsToMap(m, data.BrandingOptions)
return m
}

View file

@ -107,10 +107,11 @@ func (a *Authorize) deniedResponse(
// run the request through our go error handler
httpErr := httputil.HTTPError{
Status: int(code),
Err: errors.New(reason),
DebugURL: debugEndpoint,
RequestID: requestid.FromContext(ctx),
Status: int(code),
Err: errors.New(reason),
DebugURL: debugEndpoint,
RequestID: requestid.FromContext(ctx),
BrandingOptions: a.currentOptions.Load().BrandingOptions,
}
httpErr.ErrorResponse(ctx, w, r)

View file

@ -26,6 +26,7 @@ import (
"github.com/pomerium/pomerium/internal/directory/okta"
"github.com/pomerium/pomerium/internal/directory/onelogin"
"github.com/pomerium/pomerium/internal/hashutil"
"github.com/pomerium/pomerium/internal/httputil"
"github.com/pomerium/pomerium/internal/identity/oauth"
"github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/internal/sets"
@ -298,6 +299,8 @@ type Options struct {
CodecType CodecType `mapstructure:"codec_type" yaml:"codec_type"`
AuditKey *PublicKeyEncryptionKeyOptions `mapstructure:"audit_key"`
BrandingOptions httputil.BrandingOptions
}
type certificateFilePair struct {
@ -1544,6 +1547,7 @@ func (o *Options) ApplySettings(ctx context.Context, settings *config.Settings)
if settings.ClientCrlFile != nil {
o.ClientCRLFile = settings.GetClientCrlFile()
}
o.BrandingOptions = settings
}
func dataDir() string {

View file

@ -0,0 +1,35 @@
package httputil
// The BrandingOptions customize the user info and error pages.
type BrandingOptions interface {
GetPrimaryColor() string
GetSecondaryColor() string
GetDarkmodePrimaryColor() string
GetDarkmodeSecondaryColor() string
GetLogoUrl() string
GetFaviconUrl() string
GetErrorMessageFirstParagraph() string
}
// AddBrandingOptionsToMap adds the branding options to the map.
func AddBrandingOptionsToMap(dst map[string]any, brandingOptions BrandingOptions) {
if brandingOptions == nil {
return
}
if brandingOptions.GetPrimaryColor() != "" {
dst["primaryColor"] = brandingOptions.GetPrimaryColor()
}
if brandingOptions.GetSecondaryColor() != "" {
dst["secondaryColor"] = brandingOptions.GetSecondaryColor()
}
if brandingOptions.GetLogoUrl() != "" {
dst["logoUrl"] = brandingOptions.GetLogoUrl()
}
if brandingOptions.GetFaviconUrl() != "" {
dst["faviconUrl"] = brandingOptions.GetFaviconUrl()
}
if brandingOptions.GetErrorMessageFirstParagraph() != "" {
dst["errorMessageFirstParagraph"] = brandingOptions.GetErrorMessageFirstParagraph()
}
}

View file

@ -20,6 +20,8 @@ type HTTPError struct {
DebugURL *url.URL
// The request ID.
RequestID string
BrandingOptions BrandingOptions
}
// NewError returns an error that contains a HTTP status and error.
@ -73,7 +75,7 @@ func (e *HTTPError) ErrorResponse(ctx context.Context, w http.ResponseWriter, r
return
}
m := map[string]interface{}{
m := map[string]any{
"canDebug": response.CanDebug,
"error": response.Error,
"requestId": response.RequestID,
@ -84,6 +86,7 @@ func (e *HTTPError) ErrorResponse(ctx context.Context, w http.ResponseWriter, r
if response.DebugURL != nil {
m["debugUrl"] = response.DebugURL.String()
}
AddBrandingOptionsToMap(m, e.BrandingOptions)
w.Header().Set("Content-Type", "text/html; charset=UTF-8")
w.WriteHeader(response.Status)

View file

@ -991,6 +991,13 @@ type Settings struct {
ProgrammaticRedirectDomainWhitelist []string `protobuf:"bytes,68,rep,name=programmatic_redirect_domain_whitelist,json=programmaticRedirectDomainWhitelist,proto3" json:"programmatic_redirect_domain_whitelist,omitempty"`
AuditKey *crypt.PublicKeyEncryptionKey `protobuf:"bytes,72,opt,name=audit_key,json=auditKey,proto3,oneof" json:"audit_key,omitempty"`
CodecType *v31.HttpConnectionManager_CodecType `protobuf:"varint,73,opt,name=codec_type,json=codecType,proto3,enum=envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager_CodecType,oneof" json:"codec_type,omitempty"`
PrimaryColor *string `protobuf:"bytes,85,opt,name=primary_color,json=primaryColor,proto3,oneof" json:"primary_color,omitempty"`
SecondaryColor *string `protobuf:"bytes,86,opt,name=secondary_color,json=secondaryColor,proto3,oneof" json:"secondary_color,omitempty"`
DarkmodePrimaryColor *string `protobuf:"bytes,87,opt,name=darkmode_primary_color,json=darkmodePrimaryColor,proto3,oneof" json:"darkmode_primary_color,omitempty"`
DarkmodeSecondaryColor *string `protobuf:"bytes,88,opt,name=darkmode_secondary_color,json=darkmodeSecondaryColor,proto3,oneof" json:"darkmode_secondary_color,omitempty"`
LogoUrl *string `protobuf:"bytes,89,opt,name=logo_url,json=logoUrl,proto3,oneof" json:"logo_url,omitempty"`
FaviconUrl *string `protobuf:"bytes,90,opt,name=favicon_url,json=faviconUrl,proto3,oneof" json:"favicon_url,omitempty"`
ErrorMessageFirstParagraph *string `protobuf:"bytes,91,opt,name=error_message_first_paragraph,json=errorMessageFirstParagraph,proto3,oneof" json:"error_message_first_paragraph,omitempty"`
}
func (x *Settings) Reset() {
@ -1557,6 +1564,55 @@ func (x *Settings) GetCodecType() v31.HttpConnectionManager_CodecType {
return v31.HttpConnectionManager_CodecType(0)
}
func (x *Settings) GetPrimaryColor() string {
if x != nil && x.PrimaryColor != nil {
return *x.PrimaryColor
}
return ""
}
func (x *Settings) GetSecondaryColor() string {
if x != nil && x.SecondaryColor != nil {
return *x.SecondaryColor
}
return ""
}
func (x *Settings) GetDarkmodePrimaryColor() string {
if x != nil && x.DarkmodePrimaryColor != nil {
return *x.DarkmodePrimaryColor
}
return ""
}
func (x *Settings) GetDarkmodeSecondaryColor() string {
if x != nil && x.DarkmodeSecondaryColor != nil {
return *x.DarkmodeSecondaryColor
}
return ""
}
func (x *Settings) GetLogoUrl() string {
if x != nil && x.LogoUrl != nil {
return *x.LogoUrl
}
return ""
}
func (x *Settings) GetFaviconUrl() string {
if x != nil && x.FaviconUrl != nil {
return *x.FaviconUrl
}
return ""
}
func (x *Settings) GetErrorMessageFirstParagraph() string {
if x != nil && x.ErrorMessageFirstParagraph != nil {
return *x.ErrorMessageFirstParagraph
}
return ""
}
type Settings_Certificate struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -1926,7 +1982,7 @@ var file_config_proto_rawDesc = []byte{
0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xfa, 0x30, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x74,
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf7, 0x34, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x74,
0x69, 0x6e, 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x47, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52,
0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x88,
@ -2200,7 +2256,29 @@ var file_config_proto_rawDesc = []byte{
0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x2e, 0x76, 0x33, 0x2e, 0x48,
0x74, 0x74, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x6e,
0x61, 0x67, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x54, 0x79, 0x70, 0x65, 0x48, 0x43,
0x52, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x1a, 0x81,
0x52, 0x09, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x28,
0x0a, 0x0d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18,
0x55, 0x20, 0x01, 0x28, 0x09, 0x48, 0x44, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x73, 0x65, 0x63, 0x6f,
0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x56, 0x20, 0x01, 0x28,
0x09, 0x48, 0x45, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x43, 0x6f,
0x6c, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x39, 0x0a, 0x16, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f,
0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
0x18, 0x57, 0x20, 0x01, 0x28, 0x09, 0x48, 0x46, 0x52, 0x14, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f,
0x64, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01,
0x01, 0x12, 0x3d, 0x0a, 0x18, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x73, 0x65,
0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x58, 0x20,
0x01, 0x28, 0x09, 0x48, 0x47, 0x52, 0x16, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x53,
0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x88, 0x01, 0x01,
0x12, 0x1e, 0x0a, 0x08, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x59, 0x20, 0x01,
0x28, 0x09, 0x48, 0x48, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01,
0x12, 0x24, 0x0a, 0x0b, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18,
0x5a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x49, 0x52, 0x0a, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f, 0x6e,
0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x46, 0x0a, 0x1d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x70, 0x61,
0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x5b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x4a, 0x52,
0x1a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x69, 0x72,
0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70, 0x68, 0x88, 0x01, 0x01, 0x1a, 0x81,
0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1b,
0x0a, 0x09, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x63, 0x65, 0x72, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6b,
@ -2318,10 +2396,20 @@ var file_config_proto_rawDesc = []byte{
0x0a, 0x15, 0x5f, 0x78, 0x66, 0x66, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74,
0x65, 0x64, 0x5f, 0x68, 0x6f, 0x70, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x61, 0x75, 0x64, 0x69,
0x74, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x5f,
0x74, 0x79, 0x70, 0x65, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65,
0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x74, 0x79, 0x70, 0x65, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e,
0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x19, 0x0a, 0x17, 0x5f, 0x64,
0x61, 0x72, 0x6b, 0x6d, 0x6f, 0x64, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f,
0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x64, 0x61, 0x72, 0x6b, 0x6d, 0x6f,
0x64, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6c,
0x6f, 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72, 0x6c, 0x42,
0x0e, 0x0a, 0x0c, 0x5f, 0x66, 0x61, 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x42,
0x20, 0x0a, 0x1e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x67, 0x72, 0x61, 0x70,
0x68, 0x42, 0x2e, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75,
0x6d, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View file

@ -216,4 +216,11 @@ message Settings {
optional pomerium.crypt.PublicKeyEncryptionKey audit_key = 72;
optional envoy.extensions.filters.network.http_connection_manager.v3
.HttpConnectionManager.CodecType codec_type = 73;
optional string primary_color = 85;
optional string secondary_color = 86;
optional string darkmode_primary_color = 87;
optional string darkmode_secondary_color = 88;
optional string logo_url = 89;
optional string favicon_url = 90;
optional string error_message_first_paragraph = 91;
}