Add cusotmizable cname target domain

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-10-01 09:07:32 +02:00
parent e33bc760d5
commit 2865b484bc
7 changed files with 112 additions and 21 deletions

View File

@@ -17,6 +17,7 @@ package probod
type customDomainsConfig struct {
RenewalInterval int `json:"renewal-interval"`
ProvisionInterval int `json:"provision-interval"`
CnameTarget string `json:"cname-target"`
ACME acmeConfig `json:"acme"`
}

View File

@@ -309,9 +309,8 @@ func (impl *Implm) Run(
ConnectorRegistry: defaultConnectorRegistry,
Agent: agent,
SafeRedirect: &saferedirect.SafeRedirect{AllowedHost: impl.cfg.Hostname},
CustomDomainCname: impl.cfg.CustomDomains.CnameTarget,
Logger: l.Named("http.server"),
PgClient: pgClient,
EncryptionKey: impl.cfg.EncryptionKey,
Auth: api.ConsoleAuthConfig{
CookieName: impl.cfg.Auth.Cookie.Name,
CookieDomain: impl.cfg.Auth.Cookie.Domain,

View File

@@ -53,15 +53,16 @@ type (
}
Config struct {
AllowedOrigins []string
Probo *probo.Service
Usrmgr *usrmgr.Service
Trust *trust.Service
Auth ConsoleAuthConfig
TrustAuth TrustAuthConfig
ConnectorRegistry *connector.ConnectorRegistry
SafeRedirect *saferedirect.SafeRedirect
Logger *log.Logger
AllowedOrigins []string
Probo *probo.Service
Usrmgr *usrmgr.Service
Trust *trust.Service
Auth ConsoleAuthConfig
TrustAuth TrustAuthConfig
ConnectorRegistry *connector.ConnectorRegistry
SafeRedirect *saferedirect.SafeRedirect
CustomDomainCname string
Logger *log.Logger
}
Server struct {
@@ -154,6 +155,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
},
s.cfg.ConnectorRegistry,
s.cfg.SafeRedirect,
s.cfg.CustomDomainCname,
),
)

View File

@@ -53,9 +53,10 @@ type (
}
Resolver struct {
proboSvc *probo.Service
usrmgrSvc *usrmgr.Service
authCfg AuthConfig
proboSvc *probo.Service
usrmgrSvc *usrmgr.Service
authCfg AuthConfig
customDomainCname string
}
ctxKey struct{ name string }
@@ -84,6 +85,7 @@ func NewMux(
authCfg AuthConfig,
connectorRegistry *connector.ConnectorRegistry,
safeRedirect *saferedirect.SafeRedirect,
customDomainCname string,
) *chi.Mux {
r := chi.NewMux()
@@ -204,20 +206,21 @@ func NewMux(
}))
r.Get("/", playground.Handler("GraphQL", "/api/console/v1/query"))
r.Post("/query", graphqlHandler(logger, proboSvc, usrmgrSvc, authCfg))
r.Post("/query", graphqlHandler(logger, proboSvc, usrmgrSvc, authCfg, customDomainCname))
return r
}
func graphqlHandler(logger *log.Logger, proboSvc *probo.Service, usrmgrSvc *usrmgr.Service, authCfg AuthConfig) http.HandlerFunc {
func graphqlHandler(logger *log.Logger, proboSvc *probo.Service, usrmgrSvc *usrmgr.Service, authCfg AuthConfig, customDomainCname string) http.HandlerFunc {
var mb int64 = 1 << 20
es := schema.NewExecutableSchema(
schema.Config{
Resolvers: &Resolver{
proboSvc: proboSvc,
usrmgrSvc: usrmgrSvc,
authCfg: authCfg,
proboSvc: proboSvc,
usrmgrSvc: usrmgrSvc,
authCfg: authCfg,
customDomainCname: customDomainCname,
},
},
)

View File

@@ -0,0 +1,84 @@
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package types
import (
"github.com/getprobo/probo/pkg/coredata"
"github.com/getprobo/probo/pkg/gid"
"github.com/getprobo/probo/pkg/page"
)
func NewCustomDomainConnection(
p *page.Page[*coredata.CustomDomain, coredata.CustomDomainOrderField],
parentType any,
parentID gid.GID,
cnameTarget string,
) *CustomDomainConnection {
var edges = make([]*CustomDomainEdge, len(p.Data))
for i := range edges {
edges[i] = NewCustomDomainEdge(p.Data[i], p.Cursor.OrderBy.Field, cnameTarget)
}
return &CustomDomainConnection{
Edges: edges,
PageInfo: NewPageInfo(p),
TotalCount: len(p.Data),
}
}
func NewCustomDomainEdge(
d *coredata.CustomDomain,
orderBy coredata.CustomDomainOrderField,
cnameTarget string,
) *CustomDomainEdge {
return &CustomDomainEdge{
Cursor: d.CursorKey(orderBy),
Node: NewCustomDomain(d, cnameTarget),
}
}
func NewCustomDomain(d *coredata.CustomDomain, cnameTarget string) *CustomDomain {
result := &CustomDomain{
ID: d.ID,
Domain: d.Domain,
IsActive: d.IsActive,
SslStatus: d.SSLStatus,
CreatedAt: d.CreatedAt,
UpdatedAt: d.UpdatedAt,
SslExpiresAt: d.SSLExpiresAt,
}
// Convert DNS records
result.DNSRecords = convertDNSRecords(d, cnameTarget)
return result
}
func convertDNSRecords(d *coredata.CustomDomain, cnameTarget string) []*DNSRecordInstruction {
var records []*DNSRecordInstruction
// For HTTP-01 challenges, we just need the domain to point to our servers via CNAME
record := &DNSRecordInstruction{
Type: "CNAME",
Name: d.Domain,
Value: cnameTarget,
TTL: 300,
Purpose: "Point domain to Probo servers",
}
records = append(records, record)
return records
}

View File

@@ -3325,7 +3325,7 @@ func (r *mutationResolver) CreateCustomDomain(ctx context.Context, input types.C
}
edge := &types.CustomDomainEdge{
Node: types.NewCustomDomain(domain),
Node: types.NewCustomDomain(domain, r.customDomainCname),
Cursor: page.NewCursorKey(domain.ID, domain.CreatedAt),
}
@@ -4032,7 +4032,7 @@ func (r *organizationResolver) CustomDomains(ctx context.Context, obj *types.Org
return nil, fmt.Errorf("failed to list custom domains: %w", err)
}
return types.NewCustomDomainConnection(page, r, obj.ID), nil
return types.NewCustomDomainConnection(page, r, obj.ID, r.customDomainCname), nil
}
// TotalCount is the resolver for the totalCount field.

View File

@@ -44,6 +44,7 @@ type Config struct {
ConnectorRegistry *connector.ConnectorRegistry
Agent *agents.Agent
SafeRedirect *saferedirect.SafeRedirect
CustomDomainCname string
Logger *log.Logger
}
@@ -68,6 +69,7 @@ func NewServer(cfg Config) (*Server, error) {
TrustAuth: cfg.TrustAuth,
ConnectorRegistry: cfg.ConnectorRegistry,
SafeRedirect: cfg.SafeRedirect,
CustomDomainCname: cfg.CustomDomainCname,
Logger: cfg.Logger.Named("api"),
}
apiServer, err := api.NewServer(apiCfg)