diff --git a/.gitignore b/.gitignore index cbec6f9f8..0e9f93896 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ pem env coverage.txt +gsuite.service.account.json *.pem # Compiled Object files, Static and Dynamic libs (Shared Objects) *.o diff --git a/cmd/pomerium/main.go b/cmd/pomerium/main.go index c99c6fe47..bcc14d261 100644 --- a/cmd/pomerium/main.go +++ b/cmd/pomerium/main.go @@ -89,12 +89,11 @@ func main() { } topMux := http.NewServeMux() + topMux.HandleFunc("/ping", func(rw http.ResponseWriter, _ *http.Request) { + rw.WriteHeader(http.StatusOK) + fmt.Fprintf(rw, "OK") + }) if authenticateService != nil { - // Need to handle ping without host lookup for LB - topMux.HandleFunc("/ping", func(rw http.ResponseWriter, _ *http.Request) { - rw.WriteHeader(http.StatusOK) - fmt.Fprintf(rw, "OK") - }) topMux.Handle(authHost+"/", authenticateService.Handler()) } if proxyService != nil { diff --git a/docs/docs/examples/kubernetes/authenticate.deploy.yml b/docs/docs/examples/kubernetes/authenticate.deploy.yml index 153b857dd..135a39e32 100644 --- a/docs/docs/examples/kubernetes/authenticate.deploy.yml +++ b/docs/docs/examples/kubernetes/authenticate.deploy.yml @@ -35,8 +35,6 @@ spec: value: 851877082059-bfgkpj09noog7as3gpc3t7r6n9sjbgs6.apps.googleusercontent.com - name: PROXY_ROOT_DOMAIN value: beyondperimeter.com - - name: ALLOWED_DOMAINS - value: "*" - name: SHARED_SECRET valueFrom: secretKeyRef: @@ -52,6 +50,11 @@ spec: secretKeyRef: name: idp-client-secret key: idp-client-secret + - name: IDP_SERVICE_ACCOUNT + valueFrom: + secretKeyRef: + name: idp-service-account + key: idp-service-account - name: CERTIFICATE valueFrom: secretKeyRef: diff --git a/docs/docs/examples/kubernetes/authorize.deploy.yml b/docs/docs/examples/kubernetes/authorize.deploy.yml new file mode 100644 index 000000000..a0873ba36 --- /dev/null +++ b/docs/docs/examples/kubernetes/authorize.deploy.yml @@ -0,0 +1,59 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pomerium-authorize + labels: + app: pomerium-authorize + namespace: pomerium +spec: + replicas: 1 + selector: + matchLabels: + app: pomerium-authorize + template: + metadata: + labels: + app: pomerium-authorize + spec: + containers: + - image: pomerium/pomerium:latest + name: pomerium-authorize + ports: + - containerPort: 443 + name: https + protocol: TCP + env: + - name: POLICY + valueFrom: + configMapKeyRef: + name: policy + key: policy + - name: SERVICES + value: authorize + - name: SHARED_SECRET + valueFrom: + secretKeyRef: + name: shared-secret + key: shared-secret + - name: CERTIFICATE + valueFrom: + secretKeyRef: + name: certificate + key: certificate + - name: CERTIFICATE_KEY + valueFrom: + secretKeyRef: + name: certificate-key + key: certificate-key + readinessProbe: + httpGet: + path: /ping + port: 443 + scheme: HTTPS + livenessProbe: + httpGet: + path: /ping + port: 443 + scheme: HTTPS + initialDelaySeconds: 10 + timeoutSeconds: 1 diff --git a/docs/docs/examples/kubernetes/authorize.service.yml b/docs/docs/examples/kubernetes/authorize.service.yml new file mode 100644 index 000000000..c16bad708 --- /dev/null +++ b/docs/docs/examples/kubernetes/authorize.service.yml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: pomerium-authorize-service + namespace: pomerium + annotations: + cloud.google.com/app-protocols: '{"https":"HTTPS"}' +spec: + ports: + - port: 443 + name: https + selector: + app: pomerium-authorize + type: NodePort diff --git a/docs/docs/examples/kubernetes/ingress.yml b/docs/docs/examples/kubernetes/ingress.yml index c6bba08d6..2e2b935e2 100644 --- a/docs/docs/examples/kubernetes/ingress.yml +++ b/docs/docs/examples/kubernetes/ingress.yml @@ -23,7 +23,6 @@ spec: backend: serviceName: pomerium-proxy-service servicePort: https - - host: "auth.corp.beyondperimeter.com" http: paths: diff --git a/docs/docs/examples/kubernetes/proxy.deploy.yml b/docs/docs/examples/kubernetes/proxy.deploy.yml index 679c2d9b1..7db765805 100644 --- a/docs/docs/examples/kubernetes/proxy.deploy.yml +++ b/docs/docs/examples/kubernetes/proxy.deploy.yml @@ -50,6 +50,12 @@ spec: secretKeyRef: name: idp-client-secret key: idp-client-secret + # e.g. service account for group retrieval, e.g. gsuite + - name: IDP_SERVICE_ACCOUNT + valueFrom: + secretKeyRef: + name: idp-service-account + key: idp-service-account - name: CERTIFICATE valueFrom: secretKeyRef: @@ -60,6 +66,11 @@ spec: secretKeyRef: name: certificate-key key: certificate-key + - name: POLICY + valueFrom: + configMapKeyRef: + name: policy + key: policy readinessProbe: httpGet: path: /ping diff --git a/internal/options/email_validator.go b/internal/options/email_validator.go deleted file mode 100644 index 702ff1f92..000000000 --- a/internal/options/email_validator.go +++ /dev/null @@ -1,35 +0,0 @@ -package options // import "github.com/pomerium/pomerium/internal/options" - -import ( - "fmt" - "strings" -) - -// NewEmailValidator returns a function that checks whether a given email is valid based on a list -// of domains. The domain "*" is a wild card that matches any non-empty email. -func NewEmailValidator(domains []string) func(string) bool { - allowAll := false - for i, domain := range domains { - if domain == "*" { - allowAll = true - } - domains[i] = fmt.Sprintf("@%s", strings.ToLower(domain)) - } - - if allowAll { - return func(email string) bool { return email != "" } - } - - return func(email string) bool { - if email == "" { - return false - } - email = strings.ToLower(email) - for _, domain := range domains { - if strings.HasSuffix(email, domain) { - return true - } - } - return false - } -} diff --git a/internal/options/email_validator_test.go b/internal/options/email_validator_test.go deleted file mode 100644 index 385e1cfe2..000000000 --- a/internal/options/email_validator_test.go +++ /dev/null @@ -1,121 +0,0 @@ -package options // import "github.com/pomerium/pomerium/internal/options" - -import ( - "testing" -) - -func TestEmailValidatorValidator(t *testing.T) { - testCases := []struct { - name string - domains []string - email string - expectValid bool - }{ - { - name: "nothing should validate when domain list is empty", - domains: []string(nil), - email: "foo@example.com", - expectValid: false, - }, - { - name: "single domain validation", - domains: []string{"example.com"}, - email: "foo@example.com", - expectValid: true, - }, - { - name: "substring matches are rejected", - domains: []string{"example.com"}, - email: "foo@hackerexample.com", - expectValid: false, - }, - { - name: "no subdomain rollup happens", - domains: []string{"example.com"}, - email: "foo@bar.example.com", - expectValid: false, - }, - { - name: "multiple domain validation still rejects other domains", - domains: []string{"abc.com", "xyz.com"}, - email: "foo@example.com", - expectValid: false, - }, - { - name: "multiple domain validation still accepts emails from either domain", - domains: []string{"abc.com", "xyz.com"}, - email: "foo@abc.com", - expectValid: true, - }, - { - name: "multiple domain validation still rejects other domains", - domains: []string{"abc.com", "xyz.com"}, - email: "bar@xyz.com", - expectValid: true, - }, - { - name: "comparisons are case insensitive", - domains: []string{"Example.Com"}, - email: "foo@example.com", - expectValid: true, - }, - { - name: "comparisons are case insensitive", - domains: []string{"Example.Com"}, - email: "foo@EXAMPLE.COM", - expectValid: true, - }, - { - name: "comparisons are case insensitive", - domains: []string{"example.com"}, - email: "foo@ExAmPlE.CoM", - expectValid: true, - }, - { - name: "single wildcard allows all", - domains: []string{"*"}, - email: "foo@example.com", - expectValid: true, - }, - { - name: "single wildcard allows all", - domains: []string{"*"}, - email: "bar@gmail.com", - expectValid: true, - }, - { - name: "wildcard in list allows all", - domains: []string{"example.com", "*"}, - email: "foo@example.com", - expectValid: true, - }, - { - name: "wildcard in list allows all", - domains: []string{"example.com", "*"}, - email: "foo@gmail.com", - expectValid: true, - }, - { - name: "empty email rejected", - domains: []string{"example.com"}, - email: "", - expectValid: false, - }, - { - name: "wildcard still rejects empty emails", - domains: []string{"*"}, - email: "", - expectValid: false, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - emailValidator := NewEmailValidator(tc.domains) - valid := emailValidator(tc.email) - if valid != tc.expectValid { - t.Fatalf("expected %v, got %v", tc.expectValid, valid) - } - }) - } -} diff --git a/proxy/clients/authorize_client.go b/proxy/clients/authorize_client.go index 3bab43aea..46960b220 100644 --- a/proxy/clients/authorize_client.go +++ b/proxy/clients/authorize_client.go @@ -5,10 +5,10 @@ import ( "errors" "time" - pb "github.com/pomerium/pomerium/proto/authorize" "google.golang.org/grpc" "github.com/pomerium/pomerium/internal/sessions" + pb "github.com/pomerium/pomerium/proto/authorize" ) // Authorizer provides the authorize service interface diff --git a/scripts/kubernetes_gke.sh b/scripts/kubernetes_gke.sh index 12216a57e..b5448db6c 100755 --- a/scripts/kubernetes_gke.sh +++ b/scripts/kubernetes_gke.sh @@ -1,64 +1,47 @@ #!/bin/bash # NOTE! This will create real resources on Google's cloud. Make sure you clean up any unused # resources to avoid being billed. For reference, this tutorial cost me <10 cents for a couple of hours. +# NOTE! You must change the identity provider client secret setting, and service account setting! -# create a cluster +echo "=> creating cluster" gcloud container clusters create pomerium --num-nodes 1 -# get cluster credentials os we can use kubctl locally + +echo "=> get cluster credentials os we can use kubctl locally" gcloud container clusters get-credentials pomerium -# create `pomerium` namespace + +echo "=> create pomerium namespace" kubectl create ns pomerium -###################################################################### -#### UNCOMMENT to use helm to install cert-manager & nginx-ingress#### -###################################################################### -# setup service account for tiller used by helm -# kubectl create serviceaccount --namespace kube-system tiller -# kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller -# helm init --service-account tiller -# # update helm -# helm repo update -# kubectl get deployments -n kube-system -# # create nginx-ingress -# helm install --name nginx-ingress stable/nginx-ingress --set rbac.create=true -# # install cert-manager to auto grab lets encrypt certificates -# kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.6/deploy/manifests/00-crds.yaml -# helm repo update -# helm install --name cert-manager --namespace cert-manager stable/cert-manager -# configure Let’s Encrypt Issuer -# kubectl apply -f docs/docs/examples/kubernetes/issuer.le.prod.yml -# kubectl apply -f docs/docs/examples/kubernetes/issuer.le.stage.yml -# kubectl get certificate - -# add our policy -kubectl create configmap -n pomerium policy --from-literal=POLICY=$(cat policy.example.yaml | base64) - -# create our cryptographically random keys +echo "=> create our cryptographically random keys for $(shared-secret) and $(cookie-secret) from urandom" kubectl create secret generic -n pomerium shared-secret --from-literal=shared-secret=$(head -c32 /dev/urandom | base64) kubectl create secret generic -n pomerium cookie-secret --from-literal=cookie-secret=$(head -c32 /dev/urandom | base64) -# load TLS for pomerium services +echo "=> initiliaze secrets for TLS wild card certificates $(certificate) and $(certificate-key)" kubectl create secret generic -n pomerium certificate --from-literal=certificate=$(base64 -i cert.pem) kubectl create secret generic -n pomerium certificate-key --from-literal=certificate-key=$(base64 -i privkey.pem) -# load TLS to ingress +echo "=> load TLS to ingress" kubectl create secret tls -n pomerium pomerium-tls --key privkey.pem --cert cert.pem -# !!! IMPORTANT !!! -# YOU MUST CHANGE THE Identity Provider Client Secret -# !!! IMPORTANT !!! -# kubectl create secret generic -n pomerium idp-client-secret --from-literal=REPLACE_ME +echo "=> initiliaze a configmap setting for POLICY from $(policy.example.yaml)" +kubectl create configmap -n pomerium policy --from-literal=policy=$(cat policy.example.yaml | base64) -# Create the proxy & authenticate deployment +echo "=> setting $(idp-client-secret), you changed this right? :)" +exit 1 # comment out or delete this line once you change the following two settings +# kubectl create secret generic -n pomerium idp-client-secret --from-literal=idp-client-secret=REPLACEME +# kubectl create secret generic -n pomerium idp-service-account --from-literal=idp-service-account=$(base64 -i gsuite.service.account.json) + +echo "=> apply the proxy, authorize, and authenticate deployment configs" kubectl apply -f docs/docs/examples/kubernetes/authorize.deploy.yml kubectl apply -f docs/docs/examples/kubernetes/authenticate.deploy.yml kubectl apply -f docs/docs/examples/kubernetes/proxy.deploy.yml -# Create the proxy & authenticate services + +echo "=> apply the proxy, authorize, and authenticate service configs" kubectl apply -f docs/docs/examples/kubernetes/proxy.service.yml kubectl apply -f docs/docs/examples/kubernetes/authenticate.service.yml kubectl apply -f docs/docs/examples/kubernetes/authorize.service.yml -# Create and apply the Ingress; this is GKE specific +echo "=> create and apply the Ingress; this is GKE specific" kubectl apply -f docs/docs/examples/kubernetes/ingress.yml # Alternatively, nginx-ingress can be used