@@ -14,23 +14,20 @@
|
||||
|
||||
package probod
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
// CorsConfig contains CORS settings.
|
||||
type CorsConfig struct {
|
||||
AllowedOrigins []string `json:"allowed-origins"`
|
||||
}
|
||||
|
||||
type (
|
||||
corsConfig struct {
|
||||
AllowedOrigins []string `json:"allowed-origins"`
|
||||
}
|
||||
// ProxyProtocolConfig contains proxy protocol settings.
|
||||
type ProxyProtocolConfig struct {
|
||||
TrustedProxies []string `json:"trusted-proxies"`
|
||||
}
|
||||
|
||||
proxyProtocolConfig struct {
|
||||
TrustedProxies []net.IP `json:"trusted-proxies"`
|
||||
}
|
||||
|
||||
apiConfig struct {
|
||||
Addr string `json:"addr"`
|
||||
ProxyProtocol proxyProtocolConfig `json:"proxy-protocol"`
|
||||
Cors corsConfig `json:"cors"`
|
||||
ExtraHeaderFields map[string]string `json:"extra-header-fields"`
|
||||
}
|
||||
)
|
||||
// APIConfig contains HTTP API configuration.
|
||||
type APIConfig struct {
|
||||
Addr string `json:"addr"`
|
||||
ProxyProtocol ProxyProtocolConfig `json:"proxy-protocol"`
|
||||
Cors CorsConfig `json:"cors"`
|
||||
ExtraHeaderFields map[string]string `json:"extra-header-fields"`
|
||||
}
|
||||
|
||||
@@ -19,32 +19,33 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type (
|
||||
authConfig struct {
|
||||
Cookie cookieConfig `json:"cookie"`
|
||||
Password passwordConfig `json:"password"`
|
||||
DisableSignup bool `json:"disable-signup"`
|
||||
InvitationConfirmationTokenValidity int `json:"invitation-confirmation-token-validity"`
|
||||
PasswordResetTokenValidity int `json:"password-reset-token-validity"`
|
||||
MagicLinkTokenValidity int `json:"magic-link-token-validity"`
|
||||
SAML samlConfig `json:"saml"`
|
||||
}
|
||||
// AuthConfig contains authentication configuration.
|
||||
type AuthConfig struct {
|
||||
Cookie CookieConfig `json:"cookie"`
|
||||
Password PasswordConfig `json:"password"`
|
||||
DisableSignup bool `json:"disable-signup"`
|
||||
InvitationConfirmationTokenValidity int `json:"invitation-confirmation-token-validity"`
|
||||
PasswordResetTokenValidity int `json:"password-reset-token-validity"`
|
||||
MagicLinkTokenValidity int `json:"magic-link-token-validity"`
|
||||
SAML SAMLConfig `json:"saml"`
|
||||
}
|
||||
|
||||
cookieConfig struct {
|
||||
Domain string `json:"domain"`
|
||||
Secret string `json:"secret"`
|
||||
Duration int `json:"duration"`
|
||||
Name string `json:"name"`
|
||||
Secure bool `json:"secure"`
|
||||
}
|
||||
// CookieConfig contains session cookie configuration.
|
||||
type CookieConfig struct {
|
||||
Domain string `json:"domain"`
|
||||
Secret string `json:"secret"`
|
||||
Duration int `json:"duration"`
|
||||
Name string `json:"name"`
|
||||
Secure bool `json:"secure"`
|
||||
}
|
||||
|
||||
passwordConfig struct {
|
||||
Iterations uint32 `json:"iterations"`
|
||||
Pepper string `json:"pepper"`
|
||||
}
|
||||
)
|
||||
// PasswordConfig contains password hashing configuration.
|
||||
type PasswordConfig struct {
|
||||
Iterations int `json:"iterations"`
|
||||
Pepper string `json:"pepper"`
|
||||
}
|
||||
|
||||
func (c authConfig) GetPepperBytes() ([]byte, error) {
|
||||
func (c AuthConfig) GetPepperBytes() ([]byte, error) {
|
||||
if c.Password.Pepper == "" {
|
||||
return nil, fmt.Errorf("pepper cannot be empty")
|
||||
}
|
||||
@@ -63,7 +64,7 @@ func (c authConfig) GetPepperBytes() ([]byte, error) {
|
||||
return []byte(c.Password.Pepper), nil
|
||||
}
|
||||
|
||||
func (c authConfig) GetCookieSecretBytes() ([]byte, error) {
|
||||
func (c AuthConfig) GetCookieSecretBytes() ([]byte, error) {
|
||||
if c.Cookie.Secret == "" {
|
||||
return nil, fmt.Errorf("cookie secret cannot be empty")
|
||||
}
|
||||
|
||||
@@ -14,13 +14,12 @@
|
||||
|
||||
package probod
|
||||
|
||||
type (
|
||||
awsConfig struct {
|
||||
Region string `json:"region"`
|
||||
Bucket string `json:"bucket"`
|
||||
AccessKeyID string `json:"access-key-id"`
|
||||
SecretAccessKey string `json:"secret-access-key"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
UsePathStyle bool `json:"use-path-style"`
|
||||
}
|
||||
)
|
||||
// AWSConfig contains AWS S3 configuration.
|
||||
type AWSConfig struct {
|
||||
Region string `json:"region"`
|
||||
Bucket string `json:"bucket"`
|
||||
AccessKeyID string `json:"access-key-id"`
|
||||
SecretAccessKey string `json:"secret-access-key"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
UsePathStyle bool `json:"use-path-style"`
|
||||
}
|
||||
|
||||
@@ -23,26 +23,32 @@ import (
|
||||
"go.probo.inc/probo/pkg/connector"
|
||||
)
|
||||
|
||||
type (
|
||||
connectorConfig struct {
|
||||
Provider string `json:"provider"`
|
||||
Protocol connector.ProtocolType `json:"protocol"`
|
||||
Config connector.Connector `json:"-"`
|
||||
Settings any `json:"-"`
|
||||
// ConnectorConfig contains connector configuration.
|
||||
type ConnectorConfig struct {
|
||||
Provider string `json:"provider"`
|
||||
Protocol connector.ProtocolType `json:"protocol"`
|
||||
Config connector.Connector `json:"-"`
|
||||
RawConfig any `json:"config,omitempty"`
|
||||
Settings any `json:"-"`
|
||||
RawSettings any `json:"settings,omitempty"`
|
||||
}
|
||||
|
||||
// ConnectorConfigOAuth2 contains OAuth2 connector configuration.
|
||||
type ConnectorConfigOAuth2 struct {
|
||||
ClientID string `json:"client-id"`
|
||||
ClientSecret string `json:"client-secret"`
|
||||
RedirectURI string `json:"redirect-uri"`
|
||||
AuthURL string `json:"auth-url"`
|
||||
TokenURL string `json:"token-url"`
|
||||
Scopes []string `json:"scopes"`
|
||||
ExtraAuthParams map[string]string `json:"extra-auth-params,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Config) GetSlackSigningSecret() string {
|
||||
if c.Notifications.Slack.SigningSecret != "" {
|
||||
return c.Notifications.Slack.SigningSecret
|
||||
}
|
||||
|
||||
connectorConfigOAuth2 struct {
|
||||
ClientID string `json:"client-id"`
|
||||
ClientSecret string `json:"client-secret"`
|
||||
RedirectURI string `json:"redirect-uri"`
|
||||
AuthURL string `json:"auth-url"`
|
||||
TokenURL string `json:"token-url"`
|
||||
Scopes []string `json:"scopes"`
|
||||
ExtraAuthParams map[string]string `json:"extra-auth-params,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
func (c *config) GetSlackSigningSecret() string {
|
||||
for _, conn := range c.Connectors {
|
||||
if conn.Provider == "SLACK" {
|
||||
if settings, ok := conn.Settings.(map[string]any); ok {
|
||||
@@ -55,7 +61,7 @@ func (c *config) GetSlackSigningSecret() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *connectorConfig) UnmarshalJSON(data []byte) error {
|
||||
func (c *ConnectorConfig) UnmarshalJSON(data []byte) error {
|
||||
var tmp struct {
|
||||
Provider string `json:"provider"`
|
||||
Protocol string `json:"protocol"`
|
||||
@@ -80,7 +86,7 @@ func (c *connectorConfig) UnmarshalJSON(data []byte) error {
|
||||
|
||||
switch c.Protocol {
|
||||
case connector.ProtocolOAuth2:
|
||||
var config connectorConfigOAuth2
|
||||
var config ConnectorConfigOAuth2
|
||||
if err := json.NewDecoder(bytes.NewReader(tmp.RawConfig)).Decode(&config); err != nil {
|
||||
return fmt.Errorf("cannot unmarshal oauth2 connector config: %w", err)
|
||||
}
|
||||
|
||||
@@ -14,15 +14,17 @@
|
||||
|
||||
package probod
|
||||
|
||||
type customDomainsConfig struct {
|
||||
// CustomDomainsConfig contains custom domain configuration.
|
||||
type CustomDomainsConfig struct {
|
||||
RenewalInterval int `json:"renewal-interval"`
|
||||
ProvisionInterval int `json:"provision-interval"`
|
||||
ResolverAddr string `json:"resolver-addr"`
|
||||
CnameTarget string `json:"cname-target"`
|
||||
ACME acmeConfig `json:"acme"`
|
||||
ACME ACMEConfig `json:"acme"`
|
||||
}
|
||||
|
||||
type acmeConfig struct {
|
||||
// ACMEConfig contains ACME certificate configuration.
|
||||
type ACMEConfig struct {
|
||||
Directory string `json:"directory"`
|
||||
Email string `json:"email"`
|
||||
KeyType string `json:"key-type"`
|
||||
|
||||
@@ -14,18 +14,18 @@
|
||||
|
||||
package probod
|
||||
|
||||
type (
|
||||
mailerConfig struct {
|
||||
MailerInterval int `json:"mailer-interval"`
|
||||
SenderName string `json:"sender-name"`
|
||||
SenderEmail string `json:"sender-email"`
|
||||
SMTP smtpConfig `json:"smtp"`
|
||||
}
|
||||
// MailerConfig contains email mailer configuration.
|
||||
type MailerConfig struct {
|
||||
MailerInterval int `json:"mailer-interval"`
|
||||
SenderName string `json:"sender-name"`
|
||||
SenderEmail string `json:"sender-email"`
|
||||
SMTP SMTPConfig `json:"smtp"`
|
||||
}
|
||||
|
||||
smtpConfig struct {
|
||||
Addr string `json:"addr"`
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
TLSRequired bool `json:"tls-required"`
|
||||
}
|
||||
)
|
||||
// SMTPConfig contains SMTP server configuration.
|
||||
type SMTPConfig struct {
|
||||
Addr string `json:"addr"`
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
TLSRequired bool `json:"tls-required"`
|
||||
}
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
|
||||
package probod
|
||||
|
||||
type notificationsConfig struct {
|
||||
Mailer mailerConfig `json:"mailer"`
|
||||
Slack slackConfig `json:"slack"`
|
||||
Webhook webhookConfig `json:"webhook"`
|
||||
// NotificationsConfig contains notification configuration.
|
||||
type NotificationsConfig struct {
|
||||
Mailer MailerConfig `json:"mailer"`
|
||||
Slack SlackConfig `json:"slack"`
|
||||
Webhook WebhookConfig `json:"webhook"`
|
||||
}
|
||||
|
||||
type webhookConfig struct {
|
||||
// WebhookConfig contains webhook configuration.
|
||||
type WebhookConfig struct {
|
||||
SenderInterval int `json:"sender-interval"`
|
||||
CacheTTL int `json:"cache-ttl"`
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
package probod
|
||||
|
||||
type openaiConfig struct {
|
||||
// OpenAIConfig contains OpenAI API configuration.
|
||||
type OpenAIConfig struct {
|
||||
APIKey string `json:"api-key"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
ModelName string `json:"model-name"`
|
||||
|
||||
@@ -21,19 +21,18 @@ import (
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type (
|
||||
pgConfig struct {
|
||||
Addr string `json:"addr"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Database string `json:"database"`
|
||||
PoolSize int32 `json:"pool-size"`
|
||||
CACertBundle string `json:"ca-cert-bundle"`
|
||||
Debug bool `json:"debug"`
|
||||
}
|
||||
)
|
||||
// PgConfig contains PostgreSQL database configuration.
|
||||
type PgConfig struct {
|
||||
Addr string `json:"addr"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Database string `json:"database"`
|
||||
PoolSize int32 `json:"pool-size"`
|
||||
CACertBundle string `json:"ca-cert-bundle"`
|
||||
Debug bool `json:"debug"`
|
||||
}
|
||||
|
||||
func (cfg pgConfig) Options(options ...pg.Option) []pg.Option {
|
||||
func (cfg PgConfig) Options(options ...pg.Option) []pg.Option {
|
||||
opts := []pg.Option{
|
||||
pg.WithAddr(cfg.Addr),
|
||||
pg.WithUser(cfg.Username),
|
||||
|
||||
@@ -67,34 +67,64 @@ import (
|
||||
|
||||
type (
|
||||
Implm struct {
|
||||
cfg config
|
||||
cfg Config
|
||||
}
|
||||
|
||||
esignConfig struct {
|
||||
// FullConfig represents the complete configuration file structure.
|
||||
// This is used by bootstrap to generate the YAML config file.
|
||||
FullConfig struct {
|
||||
Unit UnitConfig `json:"unit"`
|
||||
Probod Config `json:"probod"`
|
||||
}
|
||||
|
||||
// UnitConfig contains unit framework configuration.
|
||||
UnitConfig struct {
|
||||
Metrics MetricsConfig `json:"metrics"`
|
||||
Tracing TracingConfig `json:"tracing"`
|
||||
}
|
||||
|
||||
// MetricsConfig contains metrics server configuration.
|
||||
MetricsConfig struct {
|
||||
Addr string `json:"addr"`
|
||||
}
|
||||
|
||||
// TracingConfig contains tracing configuration.
|
||||
TracingConfig struct {
|
||||
Addr string `json:"addr"`
|
||||
MaxBatchSize int `json:"max-batch-size"`
|
||||
BatchTimeout int `json:"batch-timeout"`
|
||||
ExportTimeout int `json:"export-timeout"`
|
||||
MaxQueueSize int `json:"max-queue-size"`
|
||||
}
|
||||
|
||||
// ESignConfig contains electronic signature configuration.
|
||||
ESignConfig struct {
|
||||
TSAURL string `json:"tsa-url"`
|
||||
}
|
||||
|
||||
config struct {
|
||||
BaseURL *baseurl.BaseURL `json:"base-url"`
|
||||
EncryptionKey cipher.EncryptionKey `json:"encryption-key"`
|
||||
Pg pgConfig `json:"pg"`
|
||||
Api apiConfig `json:"api"`
|
||||
Auth authConfig `json:"auth"`
|
||||
TrustCenter trustCenterConfig `json:"trust-center"`
|
||||
AWS awsConfig `json:"aws"`
|
||||
Notifications notificationsConfig `json:"notifications"`
|
||||
Connectors []connectorConfig `json:"connectors"`
|
||||
OpenAI openaiConfig `json:"openai"`
|
||||
ChromeDPAddr string `json:"chrome-dp-addr"`
|
||||
CustomDomains customDomainsConfig `json:"custom-domains"`
|
||||
SCIMBridge scimBridgeConfig `json:"scim-bridge"`
|
||||
ESign esignConfig `json:"esign"`
|
||||
// Config represents the probod application configuration.
|
||||
Config struct {
|
||||
BaseURL string `json:"base-url"`
|
||||
EncryptionKey string `json:"encryption-key"`
|
||||
Pg PgConfig `json:"pg"`
|
||||
Api APIConfig `json:"api"`
|
||||
Auth AuthConfig `json:"auth"`
|
||||
TrustCenter TrustCenterConfig `json:"trust-center"`
|
||||
AWS AWSConfig `json:"aws"`
|
||||
Notifications NotificationsConfig `json:"notifications"`
|
||||
Connectors []ConnectorConfig `json:"connectors"`
|
||||
OpenAI OpenAIConfig `json:"openai"`
|
||||
ChromeDPAddr string `json:"chrome-dp-addr"`
|
||||
CustomDomains CustomDomainsConfig `json:"custom-domains"`
|
||||
SCIMBridge SCIMBridgeConfig `json:"scim-bridge"`
|
||||
ESign ESignConfig `json:"esign"`
|
||||
}
|
||||
|
||||
trustCenterConfig struct {
|
||||
// TrustCenterConfig contains trust center server configuration.
|
||||
TrustCenterConfig struct {
|
||||
HTTPAddr string `json:"http-addr"`
|
||||
HTTPSAddr string `json:"https-addr"`
|
||||
ProxyProtocol proxyProtocolConfig `json:"proxy-protocol"`
|
||||
ProxyProtocol ProxyProtocolConfig `json:"proxy-protocol"`
|
||||
}
|
||||
)
|
||||
|
||||
@@ -105,12 +135,12 @@ var (
|
||||
|
||||
func New() *Implm {
|
||||
return &Implm{
|
||||
cfg: config{
|
||||
BaseURL: baseurl.MustParse("http://localhost:8080"),
|
||||
Api: apiConfig{
|
||||
cfg: Config{
|
||||
BaseURL: "http://localhost:8080",
|
||||
Api: APIConfig{
|
||||
Addr: "localhost:8080",
|
||||
},
|
||||
Pg: pgConfig{
|
||||
Pg: PgConfig{
|
||||
Addr: "localhost:5432",
|
||||
Username: "postgres",
|
||||
Password: "postgres",
|
||||
@@ -118,12 +148,12 @@ func New() *Implm {
|
||||
PoolSize: 100,
|
||||
},
|
||||
ChromeDPAddr: "localhost:9222",
|
||||
Auth: authConfig{
|
||||
Password: passwordConfig{
|
||||
Auth: AuthConfig{
|
||||
Password: PasswordConfig{
|
||||
Pepper: "this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes",
|
||||
Iterations: 1000000,
|
||||
},
|
||||
Cookie: cookieConfig{
|
||||
Cookie: CookieConfig{
|
||||
Name: "SSID",
|
||||
Secret: "this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes",
|
||||
Duration: 24,
|
||||
@@ -134,53 +164,53 @@ func New() *Implm {
|
||||
InvitationConfirmationTokenValidity: 3600,
|
||||
PasswordResetTokenValidity: 3600,
|
||||
MagicLinkTokenValidity: 900,
|
||||
SAML: samlConfig{
|
||||
SAML: SAMLConfig{
|
||||
SessionDuration: 604800,
|
||||
CleanupIntervalSeconds: 86400,
|
||||
DomainVerificationIntervalSeconds: 60,
|
||||
DomainVerificationResolverAddr: "8.8.8.8:53",
|
||||
},
|
||||
},
|
||||
TrustCenter: trustCenterConfig{
|
||||
TrustCenter: TrustCenterConfig{
|
||||
HTTPAddr: ":80",
|
||||
HTTPSAddr: ":443",
|
||||
},
|
||||
AWS: awsConfig{
|
||||
AWS: AWSConfig{
|
||||
Region: "us-east-1",
|
||||
Bucket: "probod",
|
||||
},
|
||||
Notifications: notificationsConfig{
|
||||
Mailer: mailerConfig{
|
||||
Notifications: NotificationsConfig{
|
||||
Mailer: MailerConfig{
|
||||
MailerInterval: 60,
|
||||
SenderEmail: "no-reply@notification.getprobo.com",
|
||||
SenderName: "Probo",
|
||||
SMTP: smtpConfig{
|
||||
SMTP: SMTPConfig{
|
||||
Addr: "localhost:1025",
|
||||
},
|
||||
},
|
||||
Slack: slackConfig{
|
||||
Slack: SlackConfig{
|
||||
SenderInterval: 60,
|
||||
},
|
||||
Webhook: webhookConfig{
|
||||
Webhook: WebhookConfig{
|
||||
SenderInterval: 5,
|
||||
CacheTTL: 86400,
|
||||
},
|
||||
},
|
||||
CustomDomains: customDomainsConfig{
|
||||
CustomDomains: CustomDomainsConfig{
|
||||
RenewalInterval: 3600,
|
||||
ProvisionInterval: 30,
|
||||
ResolverAddr: "8.8.8.8:53",
|
||||
ACME: acmeConfig{
|
||||
ACME: ACMEConfig{
|
||||
Directory: "https://acme-v02.api.letsencrypt.org/directory",
|
||||
Email: "admin@getprobo.com",
|
||||
KeyType: "EC256",
|
||||
},
|
||||
},
|
||||
SCIMBridge: scimBridgeConfig{
|
||||
SCIMBridge: SCIMBridgeConfig{
|
||||
SyncInterval: 60, // 15 minutes
|
||||
PollInterval: 30, // 30 seconds
|
||||
},
|
||||
ESign: esignConfig{
|
||||
ESign: ESignConfig{
|
||||
TSAURL: "http://timestamp.digicert.com",
|
||||
},
|
||||
},
|
||||
@@ -201,6 +231,19 @@ func (impl *Implm) Run(
|
||||
ctx, rootSpan := tracer.Start(parentCtx, "probod.Run")
|
||||
defer rootSpan.End()
|
||||
|
||||
// Parse config values that need conversion from strings to complex types
|
||||
baseURL, err := baseurl.Parse(impl.cfg.BaseURL)
|
||||
if err != nil {
|
||||
rootSpan.RecordError(err)
|
||||
return fmt.Errorf("cannot parse base URL: %w", err)
|
||||
}
|
||||
|
||||
var encryptionKey cipher.EncryptionKey
|
||||
if err := encryptionKey.UnmarshalText([]byte(impl.cfg.EncryptionKey)); err != nil {
|
||||
rootSpan.RecordError(err)
|
||||
return fmt.Errorf("cannot parse encryption key: %w", err)
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
defer cancel(context.Canceled)
|
||||
@@ -328,8 +371,8 @@ func (impl *Implm) Run(
|
||||
SessionDuration: time.Duration(impl.cfg.Auth.Cookie.Duration) * time.Hour,
|
||||
Bucket: impl.cfg.AWS.Bucket,
|
||||
TokenSecret: impl.cfg.Auth.Cookie.Secret,
|
||||
BaseURL: impl.cfg.BaseURL,
|
||||
EncryptionKey: impl.cfg.EncryptionKey,
|
||||
BaseURL: baseURL,
|
||||
EncryptionKey: encryptionKey,
|
||||
Certificate: samlCert,
|
||||
PrivateKey: samlKey,
|
||||
Logger: l.Named("iam"),
|
||||
@@ -378,8 +421,8 @@ func (impl *Implm) Run(
|
||||
slackService := slack.NewService(
|
||||
pgClient,
|
||||
impl.cfg.GetSlackSigningSecret(),
|
||||
impl.cfg.BaseURL.String(),
|
||||
impl.cfg.EncryptionKey,
|
||||
baseURL.String(),
|
||||
encryptionKey,
|
||||
impl.cfg.Auth.Cookie.Secret,
|
||||
l.Named("slack"),
|
||||
)
|
||||
@@ -395,11 +438,11 @@ func (impl *Implm) Run(
|
||||
|
||||
proboService, err := probo.NewService(
|
||||
ctx,
|
||||
impl.cfg.EncryptionKey,
|
||||
encryptionKey,
|
||||
pgClient,
|
||||
s3Client,
|
||||
impl.cfg.AWS.Bucket,
|
||||
impl.cfg.BaseURL.String(),
|
||||
baseURL.String(),
|
||||
impl.cfg.Auth.Cookie.Secret,
|
||||
agentConfig,
|
||||
html2pdfConverter,
|
||||
@@ -418,8 +461,8 @@ func (impl *Implm) Run(
|
||||
pgClient,
|
||||
s3Client,
|
||||
impl.cfg.AWS.Bucket,
|
||||
impl.cfg.BaseURL.String(),
|
||||
impl.cfg.EncryptionKey,
|
||||
baseURL.String(),
|
||||
encryptionKey,
|
||||
impl.cfg.GetSlackSigningSecret(),
|
||||
iamService,
|
||||
esignService,
|
||||
@@ -439,7 +482,7 @@ func (impl *Implm) Run(
|
||||
ESign: esignService,
|
||||
Slack: slackService,
|
||||
ConnectorRegistry: defaultConnectorRegistry,
|
||||
BaseURL: impl.cfg.BaseURL,
|
||||
BaseURL: baseURL,
|
||||
Agent: agent,
|
||||
CustomDomainCname: impl.cfg.CustomDomains.CnameTarget,
|
||||
TokenSecret: impl.cfg.Auth.Cookie.Secret,
|
||||
@@ -495,7 +538,7 @@ func (impl *Implm) Run(
|
||||
)
|
||||
|
||||
slackSenderCtx, stopSlackSender := context.WithCancel(context.Background())
|
||||
slackSender := slack.NewSender(pgClient, l.Named("slack-sender"), impl.cfg.EncryptionKey, slack.Config{
|
||||
slackSender := slack.NewSender(pgClient, l.Named("slack-sender"), encryptionKey, slack.Config{
|
||||
Interval: time.Duration(impl.cfg.Notifications.Slack.SenderInterval) * time.Second,
|
||||
})
|
||||
wg.Go(
|
||||
@@ -510,7 +553,7 @@ func (impl *Implm) Run(
|
||||
webhookSender := webhook.NewSender(pgClient, l.Named("webhook-sender"), webhook.Config{
|
||||
Interval: time.Duration(impl.cfg.Notifications.Webhook.SenderInterval) * time.Second,
|
||||
CacheTTL: time.Duration(impl.cfg.Notifications.Webhook.CacheTTL) * time.Second,
|
||||
EncryptionKey: impl.cfg.EncryptionKey,
|
||||
EncryptionKey: encryptionKey,
|
||||
})
|
||||
wg.Go(
|
||||
func() {
|
||||
@@ -560,6 +603,7 @@ func (impl *Implm) Run(
|
||||
serverHandler.TrustCenterHandler(),
|
||||
acmeService,
|
||||
proboService,
|
||||
encryptionKey,
|
||||
); err != nil {
|
||||
cancel(fmt.Errorf("trust center server crashed: %w", err))
|
||||
}
|
||||
@@ -633,7 +677,7 @@ func (impl *Implm) runApiServer(
|
||||
}
|
||||
|
||||
if len(impl.cfg.Api.ProxyProtocol.TrustedProxies) > 0 {
|
||||
policy := proxyproto.TrustProxyHeaderFrom(impl.cfg.Api.ProxyProtocol.TrustedProxies...)
|
||||
policy := proxyproto.TrustProxyHeaderFrom(parseIPs(impl.cfg.Api.ProxyProtocol.TrustedProxies)...)
|
||||
|
||||
listener = &proxyproto.Listener{
|
||||
Listener: listener,
|
||||
@@ -725,14 +769,15 @@ func (impl *Implm) runTrustCenterServer(
|
||||
trustRouter http.Handler,
|
||||
acmeService *certmanager.ACMEService,
|
||||
proboService *probo.Service,
|
||||
encryptionKey cipher.EncryptionKey,
|
||||
) error {
|
||||
tracer := tp.Tracer("go.probo.inc/probo/pkg/probod")
|
||||
ctx, span := tracer.Start(ctx, "probod.runTrustCenterServer")
|
||||
defer span.End()
|
||||
|
||||
certSelector := certmanager.NewSelector(pgClient, impl.cfg.EncryptionKey)
|
||||
certSelector := certmanager.NewSelector(pgClient, encryptionKey)
|
||||
|
||||
warmer := certmanager.NewCacheStore(pgClient, impl.cfg.EncryptionKey, l)
|
||||
warmer := certmanager.NewCacheStore(pgClient, encryptionKey, l)
|
||||
if err := warmer.WarmCache(ctx); err != nil {
|
||||
span.RecordError(err)
|
||||
l.ErrorCtx(ctx, "cannot warm certificate cache", log.Error(err))
|
||||
@@ -743,13 +788,13 @@ func (impl *Implm) runTrustCenterServer(
|
||||
renewalInterval = time.Hour
|
||||
}
|
||||
|
||||
renewer := certmanager.NewRenewer(pgClient, acmeService, impl.cfg.EncryptionKey, renewalInterval, l)
|
||||
renewer := certmanager.NewRenewer(pgClient, acmeService, encryptionKey, renewalInterval, l)
|
||||
|
||||
certProvisioningInterval := time.Duration(impl.cfg.CustomDomains.ProvisionInterval) * time.Second
|
||||
if certProvisioningInterval == 0 {
|
||||
certProvisioningInterval = 30 * time.Second
|
||||
}
|
||||
certProvisioner := certmanager.NewProvisioner(pgClient, acmeService, impl.cfg.EncryptionKey, impl.cfg.CustomDomains.CnameTarget, certProvisioningInterval, impl.cfg.CustomDomains.ResolverAddr, l)
|
||||
certProvisioner := certmanager.NewProvisioner(pgClient, acmeService, encryptionKey, impl.cfg.CustomDomains.CnameTarget, certProvisioningInterval, impl.cfg.CustomDomains.ResolverAddr, l)
|
||||
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
@@ -772,7 +817,7 @@ func (impl *Implm) runTrustCenterServer(
|
||||
|
||||
httpACMEHandler := certmanager.NewACMEChallengeHandler(
|
||||
pgClient,
|
||||
impl.cfg.EncryptionKey,
|
||||
encryptionKey,
|
||||
l.Named("http_acme_handler"),
|
||||
)
|
||||
|
||||
@@ -798,7 +843,7 @@ func (impl *Implm) runTrustCenterServer(
|
||||
defer func() { _ = listener.Close() }()
|
||||
|
||||
if len(impl.cfg.TrustCenter.ProxyProtocol.TrustedProxies) > 0 {
|
||||
policy := proxyproto.TrustProxyHeaderFrom(impl.cfg.TrustCenter.ProxyProtocol.TrustedProxies...)
|
||||
policy := proxyproto.TrustProxyHeaderFrom(parseIPs(impl.cfg.TrustCenter.ProxyProtocol.TrustedProxies)...)
|
||||
|
||||
listener = &proxyproto.Listener{
|
||||
Listener: listener,
|
||||
@@ -818,7 +863,7 @@ func (impl *Implm) runTrustCenterServer(
|
||||
|
||||
acmeHandler := certmanager.NewACMEChallengeHandler(
|
||||
pgClient,
|
||||
impl.cfg.EncryptionKey,
|
||||
encryptionKey,
|
||||
l.Named("acme_handler"),
|
||||
)
|
||||
|
||||
@@ -884,7 +929,7 @@ func (impl *Implm) runTrustCenterServer(
|
||||
defer func() { _ = listener.Close() }()
|
||||
|
||||
if len(impl.cfg.TrustCenter.ProxyProtocol.TrustedProxies) > 0 {
|
||||
policy := proxyproto.TrustProxyHeaderFrom(impl.cfg.TrustCenter.ProxyProtocol.TrustedProxies...)
|
||||
policy := proxyproto.TrustProxyHeaderFrom(parseIPs(impl.cfg.TrustCenter.ProxyProtocol.TrustedProxies)...)
|
||||
|
||||
listener = &proxyproto.Listener{
|
||||
Listener: listener,
|
||||
@@ -935,3 +980,15 @@ func (impl *Implm) runTrustCenterServer(
|
||||
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
// parseIPs converts a slice of string IP addresses to net.IP.
|
||||
// Invalid IPs are skipped.
|
||||
func parseIPs(strs []string) []net.IP {
|
||||
ips := make([]net.IP, 0, len(strs))
|
||||
for _, s := range strs {
|
||||
if ip := net.ParseIP(s); ip != nil {
|
||||
ips = append(ips, ip)
|
||||
}
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type samlConfig struct {
|
||||
// SAMLConfig contains SAML authentication configuration.
|
||||
type SAMLConfig struct {
|
||||
SessionDuration int `json:"session-duration"`
|
||||
CleanupIntervalSeconds int `json:"cleanup-interval-seconds"`
|
||||
Certificate string `json:"certificate"`
|
||||
@@ -27,14 +28,14 @@ type samlConfig struct {
|
||||
DomainVerificationResolverAddr string `json:"domain-verification-resolver-addr"`
|
||||
}
|
||||
|
||||
func (c samlConfig) SessionDurationTime() time.Duration {
|
||||
func (c SAMLConfig) SessionDurationTime() time.Duration {
|
||||
if c.SessionDuration == 0 {
|
||||
return 7 * 24 * time.Hour
|
||||
}
|
||||
return time.Duration(c.SessionDuration) * time.Second
|
||||
}
|
||||
|
||||
func (c samlConfig) CleanupInterval() time.Duration {
|
||||
func (c SAMLConfig) CleanupInterval() time.Duration {
|
||||
if c.CleanupIntervalSeconds == 0 {
|
||||
return 0
|
||||
}
|
||||
@@ -42,6 +43,6 @@ func (c samlConfig) CleanupInterval() time.Duration {
|
||||
return time.Duration(c.CleanupIntervalSeconds) * time.Second
|
||||
}
|
||||
|
||||
func (c samlConfig) DomainVerificationInterval() time.Duration {
|
||||
func (c SAMLConfig) DomainVerificationInterval() time.Duration {
|
||||
return time.Duration(c.DomainVerificationIntervalSeconds) * time.Second
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
|
||||
package probod
|
||||
|
||||
type scimBridgeConfig struct {
|
||||
// SCIMBridgeConfig contains SCIM bridge configuration.
|
||||
type SCIMBridgeConfig struct {
|
||||
// SyncInterval is the time between sync attempts for each bridge (in seconds).
|
||||
// Default: 900 (15 minutes)
|
||||
SyncInterval int `json:"sync-interval"`
|
||||
|
||||
@@ -14,9 +14,8 @@
|
||||
|
||||
package probod
|
||||
|
||||
type (
|
||||
slackConfig struct {
|
||||
SenderInterval int `json:"sender-interval"`
|
||||
SigningSecret string `json:"signing-secret"`
|
||||
}
|
||||
)
|
||||
// SlackConfig contains Slack notification configuration.
|
||||
type SlackConfig struct {
|
||||
SenderInterval int `json:"sender-interval"`
|
||||
SigningSecret string `json:"signing-secret"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user