aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2021-11-16 14:46:24 -0800
committerMike Crute <mike@crute.us>2021-11-17 07:56:10 -0800
commitcc58a3da7d647de8520e33dc4356672d2ed1a366 (patch)
tree1b232a0d51446eb6370cfb13932190d31ce053df /cmd
parenta42d794a286154a3106551e6e483861af2a9ef16 (diff)
downloadcloud-identity-broker-cc58a3da7d647de8520e33dc4356672d2ed1a366.tar.bz2
cloud-identity-broker-cc58a3da7d647de8520e33dc4356672d2ed1a366.tar.xz
cloud-identity-broker-cc58a3da7d647de8520e33dc4356672d2ed1a366.zip
Import of source code
Diffstat (limited to 'cmd')
-rw-r--r--cmd/web/server.go155
1 files changed, 155 insertions, 0 deletions
diff --git a/cmd/web/server.go b/cmd/web/server.go
new file mode 100644
index 0000000..e76b6b2
--- /dev/null
+++ b/cmd/web/server.go
@@ -0,0 +1,155 @@
1package web
2
3import (
4 "context"
5 "io/fs"
6 "log"
7 "os"
8 "time"
9
10 "code.crute.us/mcrute/cloud-identity-broker/app"
11 "code.crute.us/mcrute/cloud-identity-broker/app/controllers"
12 "code.crute.us/mcrute/cloud-identity-broker/app/middleware"
13 "code.crute.us/mcrute/cloud-identity-broker/app/models"
14 "code.crute.us/mcrute/cloud-identity-broker/auth"
15 "code.crute.us/mcrute/cloud-identity-broker/auth/github"
16
17 "code.crute.us/mcrute/golib/crypto/tls"
18 "code.crute.us/mcrute/golib/db/mongodb"
19 glecho "code.crute.us/mcrute/golib/echo"
20 glmw "code.crute.us/mcrute/golib/echo/middleware"
21 "code.crute.us/mcrute/golib/service"
22 "github.com/labstack/echo/v4"
23 echomw "github.com/labstack/echo/v4/middleware"
24 "github.com/spf13/cobra"
25 "golang.org/x/time/rate"
26)
27
28func Register(root *cobra.Command, embeddedTemplates fs.FS) {
29 webCmd := &cobra.Command{
30 Use: "web [options]",
31 Short: "Run web server",
32 Run: func(c *cobra.Command, args []string) {
33 webMain(app.NewConfigFromCmd(c), embeddedTemplates)
34 },
35 }
36
37 webCmd.Flags().StringSlice("bind", []string{":8169"}, "Addresses and ports to bind http server")
38 webCmd.Flags().StringSlice("bind-tls", []string{":8170"}, "Addresses and ports to bind https server")
39 webCmd.Flags().String("log-file", "", "Log file for combined host logs")
40 webCmd.Flags().String("tls-cache-dir", "ssl/", "Cache directory for TLS certificates")
41 webCmd.Flags().StringSlice("trusted-ip-ranges", []string{"172.19.0.0/22", "2602:803:4072::/48"}, "Comma separated list of IP ranges for trusted XFF proxies")
42 webCmd.Flags().StringSlice("management-ip-ranges", []string{"127.0.0.1/32", "::1/128", "172.19.0.0/22", "2602:803:4072::/48"}, "IP ranges for management systems")
43 webCmd.Flags().StringSlice("hostname", []string{"dev.aws-access.crute.us"}, "Hostname this server serves (can be specified multiple times)")
44 webCmd.Flags().Duration("rate-limit", 30*time.Second, "Number seconds between requests for credential resources")
45 webCmd.Flags().Duration("auth-cookie-duration", 24*time.Hour, "Expiration duration of the auth cookies")
46 webCmd.Flags().Int("rate-limit-burst", 30, "Number of burst requests allowed to credential endpoints")
47 webCmd.Flags().String("issuer-endpoint", "https://aws-access.crute.us", "Oauth issuer endpoint")
48 webCmd.Flags().String("jwt-audience", "aws-access", "Audience for issued JWTs")
49
50 webCmd.Flags().String("github-oauth-vault-path", "", "Vault material name for GitHub auth credentials")
51 webCmd.MarkFlagRequired("github-oauth-vault-path")
52
53 root.AddCommand(webCmd)
54}
55
56func webMain(cfg app.Config, embeddedTemplates fs.FS) {
57 ctx := context.Background()
58
59 s, err := glecho.NewDefaultEchoWithConfig(glecho.EchoConfig{
60 Debug: cfg.Debug,
61 Hostnames: cfg.Hostnames,
62 BindAddresses: cfg.Bind,
63 BindTLSAddresses: cfg.BindTLS,
64 TLSCacheDir: cfg.TLSCacheDir,
65 TrustedProxyIPRanges: cfg.TrustedIPRanges,
66 ManagementIPRanges: cfg.ManagementIPRanges,
67 DiskTemplates: os.DirFS(cfg.TemplatePath),
68 EmbeddedTemplates: embeddedTemplates,
69 TemplateGlob: &cfg.TemplateGlob,
70 CombinedHostLogFile: cfg.LogFile,
71 ContentSecurityPolicy: &glmw.ContentSecurityPolicyConfig{
72 DefaultSrc: []glmw.CSPDirective{
73 glmw.CSPSelf,
74 glmw.CSPUnsafeInline,
75 },
76 StyleSrc: []glmw.CSPDirective{
77 glmw.CSPSelf,
78 glmw.CSPData,
79 glmw.CSPUnsafeInline,
80 },
81 },
82 })
83 if err != nil {
84 log.Fatalf("Error building echo: %w", err)
85 }
86 if err = s.Init(); err != nil {
87 log.Fatalf("Error initializing echo: %w", err)
88 }
89
90 mongo, err := mongodb.Connect(ctx, cfg.MongoDbUri, cfg.MongodbVaultPath)
91 if err != nil {
92 log.Fatalf("Error connecting to mongodb: %w", err)
93 }
94
95 rateLimit := echomw.RateLimiter(
96 echomw.NewRateLimiterMemoryStoreWithConfig(
97 echomw.RateLimiterMemoryStoreConfig{
98 Rate: rate.Every(cfg.RateLimit),
99 Burst: cfg.RateLimitBurst,
100 ExpiresIn: time.Hour,
101 },
102 ),
103 )
104
105 as := &models.MongoDbAccountStore{Db: mongo}
106 us := &models.MongoDbUserStore{Db: mongo}
107
108 aws := &controllers.AWSAPI{Store: as}
109
110 am := &middleware.AuthenticationMiddleware{
111 Store: us,
112 CookieDuration: cfg.AuthCookieDuration,
113 GitHub: &github.GitHubAuthenticator{
114 ClientId: cfg.GitHubOauthCreds.ClientId,
115 ClientSecret: cfg.GitHubOauthCreds.ClientSecret,
116 },
117 JWTManager: &auth.JWTManager{
118 Store: us,
119 Audience: cfg.JWTAudience,
120 TokenExpires: cfg.AuthCookieDuration,
121 },
122 }
123 am.RegisterUrls(s)
124
125 api := s.Group("/api/account")
126 api.Use(glmw.VaryCookie())
127 api.Use(glmw.CacheNeverMiddleware)
128 api.Use(am.Middleware)
129 {
130 api.GET("", controllers.NewAPIAccountListHandler(as))
131 api.GET(
132 "/:account/credentials",
133 controllers.NewAPIRegionListHandler(aws),
134 )
135 api.GET(
136 "/:account/console",
137 controllers.NewAPIConsoleRedirectHandler(aws, cfg.IssuerEndpoint),
138 rateLimit,
139 )
140 api.GET(
141 "/:account/credentials/:region",
142 controllers.NewAPICredentialsHandler(aws),
143 rateLimit,
144 )
145 }
146 s.GET("/favicon.ico", echo.NotFoundHandler)
147 s.GET("/logout", controllers.LogoutHandler)
148 s.GET("/", controllers.IndexHandler, am.Middleware)
149
150 runner := service.NewAppRunner(ctx, s.Logger)
151 runner.AddJob(s.RunCertificateManager) // Cert manager has to start before server
152 runner.AddJob(tls.OcspErrorLogger(s.Logger, s.OcspErrors()))
153 runner.AddJobs(s.MakeServerJobs())
154 runner.RunForever(!cfg.DisableBackgroundJobs)
155}