Skip to content

Commit

Permalink
feat: Set CORS headers (argoproj#4990)
Browse files Browse the repository at this point in the history
Signed-off-by: Joyce Anne Piscos <[email protected]>
  • Loading branch information
joyciep committed Feb 3, 2021
1 parent 99c049b commit 8f5e17a
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 73 deletions.
51 changes: 27 additions & 24 deletions cmd/argo/commands/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,19 @@ import (

func NewServerCommand() *cobra.Command {
var (
authModes []string
configMap string
port int
baseHRef string
secure bool
htst bool
namespaced bool // --namespaced
managedNamespace string // --managed-namespace
enableOpenBrowser bool
eventOperationQueueSize int
eventWorkerCount int
frameOptions string
authModes []string
configMap string
port int
baseHRef string
secure bool
htst bool
namespaced bool // --namespaced
managedNamespace string // --managed-namespace
enableOpenBrowser bool
eventOperationQueueSize int
eventWorkerCount int
frameOptions string
accessControlAllowOrigin string
)

var command = cobra.Command{
Expand Down Expand Up @@ -102,18 +103,19 @@ See %s`, help.ArgoSever),
}

opts := apiserver.ArgoServerOpts{
BaseHRef: baseHRef,
TLSConfig: tlsConfig,
HSTS: htst,
Namespace: namespace,
Clients: clients,
RestConfig: config,
AuthModes: modes,
ManagedNamespace: managedNamespace,
ConfigName: configMap,
EventOperationQueueSize: eventOperationQueueSize,
EventWorkerCount: eventWorkerCount,
XFrameOptions: frameOptions,
BaseHRef: baseHRef,
TLSConfig: tlsConfig,
HSTS: htst,
Namespace: namespace,
Clients: clients,
RestConfig: config,
AuthModes: modes,
ManagedNamespace: managedNamespace,
ConfigName: configMap,
EventOperationQueueSize: eventOperationQueueSize,
EventWorkerCount: eventWorkerCount,
XFrameOptions: frameOptions,
AccessControlAllowOrigin: accessControlAllowOrigin,
}
browserOpenFunc := func(url string) {}
if enableOpenBrowser {
Expand Down Expand Up @@ -148,5 +150,6 @@ See %s`, help.ArgoSever),
command.Flags().IntVar(&eventOperationQueueSize, "event-operation-queue-size", 16, "how many events operations that can be queued at once")
command.Flags().IntVar(&eventWorkerCount, "event-worker-count", 4, "how many event workers to run")
command.Flags().StringVar(&frameOptions, "x-frame-options", "DENY", "Set X-Frame-Options header in HTTP responses.")
command.Flags().StringVar(&accessControlAllowOrigin, "access-control-allow-origin", "", "Set Access-Control-Allow-Origin header in HTTP responses.")
return &command
}
25 changes: 13 additions & 12 deletions docs/cli/argo_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@ See https://argoproj.github.io/argo/argo-server.md
### Options

```
--auth-mode stringArray API server authentication mode. Any 1 or more length permutation of: client,server,sso (default [server])
--basehref string Value for base href in index.html. Used if the server is running behind reverse proxy under subpath different from /. Defaults to the environment variable BASE_HREF. (default "/")
-b, --browser enable automatic launching of the browser [local mode]
--configmap string Name of K8s configmap to retrieve workflow controller configuration (default "workflow-controller-configmap")
--event-operation-queue-size int how many events operations that can be queued at once (default 16)
--event-worker-count int how many event workers to run (default 4)
-h, --help help for server
--hsts Whether or not we should add a HTTP Secure Transport Security header. This only has effect if secure is enabled. (default true)
--managed-namespace string namespace that watches, default to the installation namespace
--namespaced run as namespaced mode
-p, --port int Port to listen on (default 2746)
--x-frame-options string Set X-Frame-Options header in HTTP responses. (default "DENY")
--access-control-allow-origin string Set Access-Control-Allow-Origin header in HTTP responses.
--auth-mode stringArray API server authentication mode. Any 1 or more length permutation of: client,server,sso (default [server])
--basehref string Value for base href in index.html. Used if the server is running behind reverse proxy under subpath different from /. Defaults to the environment variable BASE_HREF. (default "/")
-b, --browser enable automatic launching of the browser [local mode]
--configmap string Name of K8s configmap to retrieve workflow controller configuration (default "workflow-controller-configmap")
--event-operation-queue-size int how many events operations that can be queued at once (default 16)
--event-worker-count int how many event workers to run (default 4)
-h, --help help for server
--hsts Whether or not we should add a HTTP Secure Transport Security header. This only has effect if secure is enabled. (default true)
--managed-namespace string namespace that watches, default to the installation namespace
--namespaced run as namespaced mode
-p, --port int Port to listen on (default 2746)
--x-frame-options string Set X-Frame-Options header in HTTP responses. (default "DENY")
```

### Options inherited from parent commands
Expand Down
67 changes: 35 additions & 32 deletions server/apiserver/argoserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,19 @@ const (
type argoServer struct {
baseHRef string
// https://itnext.io/practical-guide-to-securing-grpc-connections-with-go-and-tls-part-1-f63058e9d6d1
tlsConfig *tls.Config
hsts bool
namespace string
managedNamespace string
clients *types.Clients
gatekeeper auth.Gatekeeper
oAuth2Service sso.Interface
configController config.Controller
stopCh chan struct{}
eventQueueSize int
eventWorkerCount int
xframeOptions string
tlsConfig *tls.Config
hsts bool
namespace string
managedNamespace string
clients *types.Clients
gatekeeper auth.Gatekeeper
oAuth2Service sso.Interface
configController config.Controller
stopCh chan struct{}
eventQueueSize int
eventWorkerCount int
xframeOptions string
accessControlAllowOrigin string
}

type ArgoServerOpts struct {
Expand All @@ -86,12 +87,13 @@ type ArgoServerOpts struct {
RestConfig *rest.Config
AuthModes auth.Modes
// config map name
ConfigName string
ManagedNamespace string
HSTS bool
EventOperationQueueSize int
EventWorkerCount int
XFrameOptions string
ConfigName string
ManagedNamespace string
HSTS bool
EventOperationQueueSize int
EventWorkerCount int
XFrameOptions string
AccessControlAllowOrigin string
}

func NewArgoServer(ctx context.Context, opts ArgoServerOpts) (*argoServer, error) {
Expand All @@ -115,19 +117,20 @@ func NewArgoServer(ctx context.Context, opts ArgoServerOpts) (*argoServer, error
return nil, err
}
return &argoServer{
baseHRef: opts.BaseHRef,
tlsConfig: opts.TLSConfig,
hsts: opts.HSTS,
namespace: opts.Namespace,
managedNamespace: opts.ManagedNamespace,
clients: opts.Clients,
gatekeeper: gatekeeper,
oAuth2Service: ssoIf,
configController: configController,
stopCh: make(chan struct{}),
eventQueueSize: opts.EventOperationQueueSize,
eventWorkerCount: opts.EventWorkerCount,
xframeOptions: opts.XFrameOptions,
baseHRef: opts.BaseHRef,
tlsConfig: opts.TLSConfig,
hsts: opts.HSTS,
namespace: opts.Namespace,
managedNamespace: opts.ManagedNamespace,
clients: opts.Clients,
gatekeeper: gatekeeper,
oAuth2Service: ssoIf,
configController: configController,
stopCh: make(chan struct{}),
eventQueueSize: opts.EventOperationQueueSize,
eventWorkerCount: opts.EventWorkerCount,
xframeOptions: opts.XFrameOptions,
accessControlAllowOrigin: opts.AccessControlAllowOrigin,
}, nil
}

Expand Down Expand Up @@ -307,7 +310,7 @@ func (as *argoServer) newHTTPServer(ctx context.Context, port int, artifactServe
mux.HandleFunc("/oauth2/callback", as.oAuth2Service.HandleCallback)
mux.Handle("/metrics", promhttp.Handler())
// we only enable HTST if we are secure mode, otherwise you would never be able access the UI
mux.HandleFunc("/", static.NewFilesServer(as.baseHRef, as.tlsConfig != nil && as.hsts, as.xframeOptions).ServerFiles)
mux.HandleFunc("/", static.NewFilesServer(as.baseHRef, as.tlsConfig != nil && as.hsts, as.xframeOptions, as.accessControlAllowOrigin).ServerFiles)
return &httpServer
}

Expand Down
23 changes: 18 additions & 5 deletions server/static/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import (
)

type FilesServer struct {
baseHRef string
hsts bool
xframeOpts string
baseHRef string
hsts bool
xframeOpts string
corsAllowOrigin string
}

func NewFilesServer(baseHRef string, hsts bool, xframeOpts string) *FilesServer {
return &FilesServer{baseHRef, hsts, xframeOpts}
func NewFilesServer(baseHRef string, hsts bool, xframeOpts string, corsAllowOrigin string) *FilesServer {
return &FilesServer{baseHRef, hsts, xframeOpts, corsAllowOrigin}
}

func (s *FilesServer) ServerFiles(w http.ResponseWriter, r *http.Request) {
Expand All @@ -31,6 +32,18 @@ func (s *FilesServer) ServerFiles(w http.ResponseWriter, r *http.Request) {
if s.xframeOpts != "" {
w.Header().Set("X-Frame-Options", s.xframeOpts)
}

if s.corsAllowOrigin != "" {
w.Header().Set("Access-Control-Allow-Origin", s.corsAllowOrigin)
if r.Method == http.MethodOptions { // Set CORS headers for preflight request
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
w.WriteHeader(http.StatusNoContent)
return
}
}

// `data:` is need for Monaco editors wiggly red lines
w.Header().Set("Content-Security-Policy", "default-src 'self' 'unsafe-inline'; img-src 'self' data:")
if s.hsts {
Expand Down

0 comments on commit 8f5e17a

Please sign in to comment.