Skip to content

Commit

Permalink
feat: Add TLS support. Closes argoproj#2764 (argoproj#2766)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexec committed Apr 23, 2020
1 parent 510e11b commit 0dbd78f
Show file tree
Hide file tree
Showing 27 changed files with 265 additions and 63 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ debug.test
/workflow-controller
/.scannerwork/
/test-results/
/argo-server.crt
/argo-server.key
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ RUN touch ui/dist/node_modules.marker
RUN touch ui/dist/app/index.html
# fail the build if we are "dirty"
RUN git diff --exit-code
RUN make argo-server.crt argo-server.key
RUN if [ "${IMAGE_OS}" = "linux" -a "${IMAGE_ARCH}" = "amd64" ]; then \
make dist/argo-linux-amd64 dist/workflow-controller-linux-amd64 dist/argoexec-linux-amd64; \
elif [ "${IMAGE_OS}" = "linux" -a "${IMAGE_ARCH}" = "arm64" ]; then \
Expand Down Expand Up @@ -136,5 +137,7 @@ ENTRYPOINT [ "workflow-controller" ]
FROM scratch as argocli
COPY --from=argoexec-base /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts
COPY --from=argoexec-base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=argo-build /go/src/github.com/argoproj/argo/argo-server.crt argo-server.crt
COPY --from=argo-build /go/src/github.com/argoproj/argo/argo-server.key argo-server.key
COPY --from=argo-build /go/src/github.com/argoproj/argo/dist/argo-linux-* /bin/argo
ENTRYPOINT [ "argo" ]
2 changes: 2 additions & 0 deletions Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,7 @@ ENTRYPOINT [ "workflow-controller" ]
FROM scratch as argocli
COPY --from=argoexec-base /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts
COPY --from=argoexec-base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY argo-server.crt argo-server.crt
COPY argo-server.key argo-server.key
COPY argo /bin/
ENTRYPOINT [ "argo" ]
27 changes: 18 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ endif
# version change, so does the file location
MANIFESTS_VERSION_FILE := dist/$(MANIFESTS_VERSION).manifests-version
VERSION_FILE := dist/$(VERSION).version
CLI_IMAGE_FILE := dist/cli-image.$(VERSION)
EXECUTOR_IMAGE_FILE := dist/executor-image.$(VERSION)
CONTROLLER_IMAGE_FILE := dist/controller-image.$(VERSION)

# perform static compilation
STATIC_BUILD ?= true
Expand Down Expand Up @@ -164,10 +167,16 @@ dist/argo-linux-s390x: GOARGS = GOOS=linux GOARCH=s390x
dist/argo-%: server/static/files.go $(CLI_PKGS)
CGO_ENABLED=0 $(GOARGS) go build -v -i -ldflags '${LDFLAGS}' -o $@ ./cmd/argo


argo-server.crt: argo-server.key

argo-server.key:
openssl req -x509 -newkey rsa:4096 -keyout argo-server.key -out argo-server.crt -days 365 -nodes -subj /CN=localhost/O=ArgoProj

.PHONY: cli-image
cli-image: dist/cli-image
cli-image: $(CLI_IMAGE_FILE)

dist/cli-image: dist/argo-$(OUTPUT_IMAGE_OS)-$(OUTPUT_IMAGE_ARCH)
$(CLI_IMAGE_FILE): dist/argo-$(OUTPUT_IMAGE_OS)-$(OUTPUT_IMAGE_ARCH) argo-server.crt argo-server.key
# Create CLI image
ifeq ($(DEV_IMAGE),true)
cp dist/argo-$(OUTPUT_IMAGE_OS)-$(OUTPUT_IMAGE_ARCH) argo
Expand All @@ -179,7 +188,7 @@ endif
ifeq ($(K3D),true)
k3d import-images $(IMAGE_NAMESPACE)/argocli:$(VERSION)
endif
touch dist/cli-image
touch $(CLI_IMAGE_FILE)

.PHONY: clis
clis: dist/argo-linux-amd64 dist/argo-linux-arm64 dist/argo-linux-ppc64le dist/argo-linux-s390x dist/argo-darwin-amd64 dist/argo-windows-amd64 cli-image
Expand All @@ -193,9 +202,9 @@ dist/workflow-controller-%: $(CONTROLLER_PKGS)
CGO_ENABLED=0 $(GOARGS) go build -v -i -ldflags '${LDFLAGS}' -o $@ ./cmd/workflow-controller

.PHONY: controller-image
controller-image: dist/controller-image
controller-image: $(CONTROLLER_IMAGE_FILE)

dist/controller-image: dist/workflow-controller-$(OUTPUT_IMAGE_OS)-$(OUTPUT_IMAGE_ARCH)
$(CONTROLLER_IMAGE_FILE): dist/workflow-controller-$(OUTPUT_IMAGE_OS)-$(OUTPUT_IMAGE_ARCH)
# Create controller image
ifeq ($(DEV_IMAGE),true)
cp dist/workflow-controller-$(OUTPUT_IMAGE_OS)-$(OUTPUT_IMAGE_ARCH) workflow-controller
Expand All @@ -207,7 +216,7 @@ endif
ifeq ($(K3D),true)
k3d import-images $(IMAGE_NAMESPACE)/workflow-controller:$(VERSION)
endif
touch dist/controller-image
touch $(CONTROLLER_IMAGE_FILE)

# argoexec

Expand All @@ -218,9 +227,9 @@ dist/argoexec-%: $(ARGOEXEC_PKGS)
CGO_ENABLED=0 $(GOARGS) go build -v -i -ldflags '${LDFLAGS}' -o $@ ./cmd/argoexec

.PHONY: executor-image
executor-image: dist/executor-image
executor-image: $(EXECUTOR_IMAGE_FILE)

dist/executor-image: dist/argoexec-$(OUTPUT_IMAGE_OS)-$(OUTPUT_IMAGE_ARCH)
$(EXECUTOR_IMAGE_FILE): dist/argoexec-$(OUTPUT_IMAGE_OS)-$(OUTPUT_IMAGE_ARCH)
# Create executor image
ifeq ($(DEV_IMAGE),true)
cp dist/argoexec-$(OUTPUT_IMAGE_OS)-$(OUTPUT_IMAGE_ARCH) argoexec
Expand All @@ -232,7 +241,7 @@ endif
ifeq ($(K3D),true)
k3d import-images $(IMAGE_NAMESPACE)/argoexec:$(VERSION)
endif
touch dist/executor-image
touch $(EXECUTOR_IMAGE_FILE)

# generation

Expand Down
20 changes: 15 additions & 5 deletions cmd/argo/commands/client/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/argoproj/argo/util/kubeconfig"
)

var argoServer string
var argoServerOpts = apiclient.ArgoServerOpts{}

var overrides = clientcmd.ConfigOverrides{}

Expand All @@ -32,13 +32,23 @@ func GetConfig() clientcmd.ClientConfig {
}

func AddArgoServerFlagsToCmd(cmd *cobra.Command) {
cmd.PersistentFlags().StringVar(&argoServer, "argo-server", os.Getenv("ARGO_SERVER"), "API server `host:port`. e.g. localhost:2746. Defaults to the ARGO_SERVER environment variable.")
// "-s" like kubectl
cmd.PersistentFlags().StringVarP(&argoServerOpts.URL, "argo-server", "s", os.Getenv("ARGO_SERVER"), "API server `host:port`. e.g. localhost:2746. Defaults to the ARGO_SERVER environment variable.")
// "-e" for encrypted - like zip
cmd.PersistentFlags().BoolVarP(&argoServerOpts.Secure, "secure", "e", os.Getenv("ARGO_SECURE") == "true", "Whether or not the server is using TLS with the Argo Server. Defaults to the ARGO_SECURE environment variable.")
// "-k" like curl
cmd.PersistentFlags().BoolVarP(&argoServerOpts.InsecureSkipVerify, "insecure-skip-verify", "k", os.Getenv("ARGO_INSECURE_SKIP_VERIFY") == "true", "If true, the Argo Server's certificate will not be checked for validity. This will make your HTTPS connections insecure. Defaults to the ARGO_SECURE environment variable.")
}

func NewAPIClient() (context.Context, apiclient.Client) {
ctx, client, err := apiclient.NewClient(argoServer, func() string {
return GetAuthString()
}, GetConfig())
ctx, client, err := apiclient.NewClientFromOpts(
apiclient.Opts{
ArgoServerOpts: argoServerOpts,
AuthSupplier: func() string {
return GetAuthString()
},
ClientConfig: GetConfig(),
})
if err != nil {
log.Fatal(err)
}
Expand Down
21 changes: 19 additions & 2 deletions cmd/argo/commands/server.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package commands

import (
"crypto/tls"
"fmt"
"os"
"time"

"github.com/argoproj/pkg/errors"
"github.com/argoproj/pkg/stats"
log "github.com/sirupsen/logrus"
"github.com/skratchdot/open-golang/open"
Expand All @@ -25,6 +27,7 @@ func NewServerCommand() *cobra.Command {
configMap string
port int
baseHRef string
secure bool
namespaced bool // --namespaced
managedNamespace string // --managed-namespace
enableOpenBrowser bool
Expand Down Expand Up @@ -66,11 +69,23 @@ See %s`, help.ArgoSever),
"authMode": authMode,
"namespace": namespace,
"managedNamespace": managedNamespace,
"baseHRef": baseHRef}).
Info()
"baseHRef": baseHRef,
"secure": secure,
}).Info()

var tlsConfig *tls.Config
if secure {
cer, err := tls.LoadX509KeyPair("argo-server.crt", "argo-server.key")
errors.CheckError(err)
// InsecureSkipVerify will not impact the TLS listener. It is needed for the server to speak to itself for GRPC.
tlsConfig = &tls.Config{Certificates: []tls.Certificate{cer}, InsecureSkipVerify: true}
} else {
log.Warn("You are running in insecure mode. How enable transport security: https://github.com/argoproj/argo/blob/master/docs/tls.md")
}

opts := apiserver.ArgoServerOpts{
BaseHRef: baseHRef,
TLSConfig: tlsConfig,
Namespace: namespace,
WfClientSet: wflientset,
KubeClientset: kubeConfig,
Expand Down Expand Up @@ -104,6 +119,8 @@ See %s`, help.ArgoSever),
defaultBaseHRef = "/"
}
command.Flags().StringVar(&baseHRef, "basehref", defaultBaseHRef, "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.")
// "-e" for encrypt, like zip
command.Flags().BoolVarP(&secure, "secure", "e", false, "Whether or not we should listen on TLS.")
command.Flags().StringVar(&authMode, "auth-mode", "server", "API server authentication mode. One of: client|server|hybrid")
command.Flags().StringVar(&configMap, "configmap", "workflow-controller-configmap", "Name of K8s configmap to retrieve workflow controller configuration")
command.Flags().BoolVar(&namespaced, "namespaced", false, "run as namespaced mode")
Expand Down
4 changes: 4 additions & 0 deletions docs/argo-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,7 @@ See [managed namespace](managed-namespace.md).
If the server is running behind reverse proxy with a subpath different from `/` (for example,
`/argo`), you can set an alternative subpath with the `--base-href` flag or the `BASE_HREF`
environment variable.

### Transport Layer Security

See [TLS](tls.md).
2 changes: 2 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ To do so, set the ARGO_SERVER environment variable, e.g.:
```
export ARGO_SERVER=localhost:2746
```

See [TLS](tls.md).
15 changes: 15 additions & 0 deletions docs/security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Security

## Argo Server Security

Argo Server implements security in three layers.

Firstly, you should enable [transport layer security](tls.md) to ensure your data cannot be read in transit.

Secondly, you should enable an [authentication mode](argo-server.md#auth-mode) to ensure that you do not run workflows from unknown users.

Finally, you should configure the `argo-server` role and role binding with the correct permissions.

### Read-Only

You can achieve this by configuring the `argo-server` role ([example](../manifests/namespace-install/argo-server-rbac/argo-server-role.yaml) with only read access (i.e. only `get`/`list`/`watch` verbs).
68 changes: 68 additions & 0 deletions docs/tls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Transport Layer Security

![alpha](assets/alpha.svg)

> v2.9 and after
If you're running Argo Server you have three options with increasing transport security (note - you should also be running [authentication](argo-server.md#auth-mode)):

## Plain Text

*Recommended for: dev*

This is the default setting: everything is sent in plain text.

To secure the UI you may front it with a HTTPS proxy.

## Encrypted

*Recommended for: development and test environments*

You can encrypt connections without any real effort.

Start Argo Server with the `--secure` flag, e.g.:

```
argo server --secure
```

It will start with a self-signed certificate that expires after 365 days.

Run the CLI with `--secure` (or `ARGO_SECURE=true`) and `--insecure-skip-verify` (or `ARGO_INSECURE_SKIP_VERIFY=true`).

```
argo --secure --insecure-skip-verify list
```

```
export ARGO_SECURE=true
export ARGO_INSECURE_SKIP_VERIFY=true
argo --secure --insecure-skip-verify list
```

Tip: Don't forget to update your readiness probe to use HTTPS, [example](../test/e2e/manifests/mixins/argo-server-deployment.yaml).

### Encrypted and Verified

*Recommended for: production environments*

Run your HTTPS proxy in front of the Argo Server. You'll need to set-up your certificates and this out of scope of this documentation.

Start Argo Server with the `--secure` flag, e.g.:

```
argo server --secure
```

As before, it will start with a self-signed certificate that expires after 365 days.

Run the CLI with `--secure` (or `ARGO_SECURE=true`) only.

```
argo --secure list
```

```
export ARGO_SECURE=true
argo --secure --insecure-skip-verify list
```
12 changes: 1 addition & 11 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ require (
cloud.google.com/go v0.55.0 // indirect
cloud.google.com/go/storage v1.6.0
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
github.com/ajg/form v1.5.1 // indirect
github.com/aliyun/aliyun-oss-go-sdk v2.0.6+incompatible
github.com/argoproj/pkg v0.0.0-20200318225345-d3be5f29b1a8
github.com/aws/aws-sdk-go v1.27.1 // indirect
Expand All @@ -18,9 +17,9 @@ require (
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
github.com/evanphx/json-patch v4.2.0+incompatible
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gavv/httpexpect/v2 v2.0.3
github.com/ghodss/yaml v1.0.0
github.com/go-ini/ini v1.51.1 // indirect
github.com/go-openapi/jsonreference v0.19.3 // indirect
Expand All @@ -29,7 +28,6 @@ require (
github.com/go-sql-driver/mysql v1.4.1
github.com/gogo/protobuf v1.3.1
github.com/golang/protobuf v1.3.5
github.com/google/go-querystring v1.0.0 // indirect
github.com/googleapis/gnostic v0.3.1 // indirect
github.com/gophercloud/gophercloud v0.7.0 // indirect
github.com/gorilla/websocket v1.4.1
Expand All @@ -42,7 +40,6 @@ require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jcmturner/gofork v1.0.0 // indirect
github.com/json-iterator/go v1.1.9 // indirect
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
github.com/klauspost/compress v1.9.7 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/kr/pretty v0.2.0 // indirect
Expand All @@ -52,7 +49,6 @@ require (
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/minio/minio-go v6.0.14+incompatible // indirect
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b
github.com/moul/http2curl v1.0.0 // indirect
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.0.0
github.com/prometheus/client_model v0.1.0
Expand All @@ -69,22 +65,16 @@ require (
github.com/spf13/cobra v0.0.4-0.20181021141114-fe5e611709b0
github.com/stretchr/testify v1.5.1
github.com/tidwall/gjson v1.3.5
github.com/valyala/fasthttp v0.0.0-20171207120941-e5f51c11919d // indirect
github.com/valyala/fasttemplate v1.1.0
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect
github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
github.com/yudai/pp v2.0.1+incompatible // indirect
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4
golang.org/x/net v0.0.0-20200301022130-244492dfa37a
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/tools v0.0.0-20200414205525-6a72e3782ce5 // indirect
google.golang.org/api v0.20.0
google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24
google.golang.org/grpc v1.28.0
gopkg.in/gavv/httpexpect.v2 v2.0.0
gopkg.in/ini.v1 v1.54.0 // indirect
gopkg.in/jcmturner/goidentity.v2 v2.0.0 // indirect
gopkg.in/jcmturner/gokrb5.v5 v5.3.0
Expand Down
Loading

0 comments on commit 0dbd78f

Please sign in to comment.