Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
23 changes: 11 additions & 12 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
module github.com/openshift/oauth-proxy

go 1.13
go 1.15

require (
github.com/18F/hmacauth v0.0.0-20151013130326-9232a6386b73
github.com/BurntSushi/toml v0.3.1
github.com/bitly/go-simplejson v0.5.1-0.20170206154632-da1a8928f709
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869
github.com/fsnotify/fsnotify v1.4.7
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 // indirect
github.com/mreiferson/go-options v0.0.0-20161229190002-77551d20752b
github.com/openshift/library-go v0.0.0-20190731063920-9fac0f4cee90
github.com/fsnotify/fsnotify v1.4.9
github.com/mreiferson/go-options v1.0.0
github.com/openshift/library-go v0.0.0-20200918101923-1e4c94603efe
github.com/yhat/wsutil v0.0.0-20170731153501-1d66fa95c997
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9
golang.org/x/text v0.3.3 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
k8s.io/api v0.17.0
k8s.io/apimachinery v0.17.0
k8s.io/apiserver v0.17.0
k8s.io/client-go v0.17.0
golang.org/x/net v0.0.0-20200904194848-62affa334b73
k8s.io/api v0.19.2
k8s.io/apimachinery v0.19.2
k8s.io/apiserver v0.19.2
k8s.io/client-go v0.19.2
)

replace vbom.ml/util => github.com/fvbommel/util v0.0.0-20180919145318-efcd4e0f9787
451 changes: 434 additions & 17 deletions go.sum

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ func main() {
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
flagSet := flag.NewFlagSet("oauth2_proxy", flag.ExitOnError)

emailDomains := StringArray{}
upstreams := StringArray{}
skipAuthRegex := StringArray{}
bypassAuthRegex := StringArray{}
bypassAuthExceptRegex := StringArray{}
openshiftCAs := StringArray{}
emailDomains := NewStringArray()
upstreams := NewStringArray()
skipAuthRegex := NewStringArray()
bypassAuthRegex := NewStringArray()
bypassAuthExceptRegex := NewStringArray()
openshiftCAs := NewStringArray()
clientCA := ""
upstreamCAs := StringArray{}
upstreamCAs := NewStringArray()

config := flagSet.String("config", "", "path to config file")
showVersion := flagSet.Bool("version", false, "print version string")
Expand All @@ -41,22 +41,22 @@ func main() {
flagSet.StringVar(&clientCA, "tls-client-ca", clientCA, "path to a CA file for admitting client certificates.")
flagSet.String("redirect-url", "", "the OAuth Redirect URL. ie: \"https://internalapp.yourcompany.com/oauth/callback\"")
flagSet.Bool("set-xauthrequest", false, "set X-Auth-Request-User and X-Auth-Request-Email response headers (useful in Nginx auth_request mode)")
flagSet.Var(&upstreams, "upstream", "the http url(s) of the upstream endpoint or file:// paths for static files. Routing is based on the path")
flagSet.Var(upstreams, "upstream", "the http url(s) of the upstream endpoint or file:// paths for static files. Routing is based on the path")
flagSet.Bool("pass-basic-auth", true, "pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream")
flagSet.Bool("pass-user-headers", true, "pass X-Forwarded-User and X-Forwarded-Email information to upstream")
flagSet.String("basic-auth-password", "", "the password to set when passing the HTTP Basic Auth header")
flagSet.Bool("pass-access-token", false, "pass OAuth access_token to upstream via X-Forwarded-Access-Token header")
flagSet.Bool("pass-user-bearer-token", false, "pass OAuth access token received from the client to upstream via X-Forwarded-Access-Token header")
flagSet.Bool("pass-host-header", true, "pass the request Host Header to upstream")
flagSet.Var(&bypassAuthExceptRegex, "bypass-auth-except-for", "provide authentication ONLY for request paths under proxy-prefix and those that match the given regex (may be given multiple times). Cannot be set with -skip-auth-regex/-bypass-auth-for")
flagSet.Var(&bypassAuthRegex, "bypass-auth-for", "alias for skip-auth-regex")
flagSet.Var(&skipAuthRegex, "skip-auth-regex", "bypass authentication for request paths that match (may be given multiple times). Cannot be set with -bypass-auth-except-for. Alias for -bypass-auth-for")
flagSet.Var(bypassAuthExceptRegex, "bypass-auth-except-for", "provide authentication ONLY for request paths under proxy-prefix and those that match the given regex (may be given multiple times). Cannot be set with -skip-auth-regex/-bypass-auth-for")
flagSet.Var(bypassAuthRegex, "bypass-auth-for", "alias for skip-auth-regex")
flagSet.Var(skipAuthRegex, "skip-auth-regex", "bypass authentication for request paths that match (may be given multiple times). Cannot be set with -bypass-auth-except-for. Alias for -bypass-auth-for")
flagSet.Bool("skip-provider-button", false, "will skip sign-in-page to directly reach the next step: oauth/start")
flagSet.Bool("skip-auth-preflight", false, "will skip authentication for OPTIONS requests")
flagSet.Bool("ssl-insecure-skip-verify", false, "skip validation of certificates presented when using HTTPS")
flagSet.String("debug-address", "", "[http://]<addr>:<port> or unix://<path> to listen on for debug and requests")

flagSet.Var(&emailDomains, "email-domain", "authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email")
flagSet.Var(emailDomains, "email-domain", "authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email")
flagSet.String("client-id", "", "the OAuth Client ID: ie: \"123456.apps.googleusercontent.com\"")
flagSet.String("client-secret", "", "the OAuth Client Secret")
flagSet.String("client-secret-file", "", "a file containing the client-secret")
Expand All @@ -71,7 +71,7 @@ func main() {
flagSet.String("openshift-group", "", "restrict logins to members of this group (or groups, if encoded as a JSON array).")
flagSet.String("openshift-sar", "", "require this encoded subject access review to authorize (may be a JSON list).")
flagSet.String("openshift-sar-by-host", "", "require this encoded subject access review to authorize (must be a JSON array).")
flagSet.Var(&openshiftCAs, "openshift-ca", "paths to CA roots for the OpenShift API (may be given multiple times, defaults to /var/run/secrets/kubernetes.io/serviceaccount/ca.crt).")
flagSet.Var(openshiftCAs, "openshift-ca", "paths to CA roots for the OpenShift API (may be given multiple times, defaults to /var/run/secrets/kubernetes.io/serviceaccount/ca.crt).")
flagSet.String("openshift-review-url", "", "Permission check endpoint (defaults to the subject access review endpoint)")
flagSet.String("openshift-delegate-urls", "", "If set, perform delegated authorization against the OpenShift API server. Value is a JSON map of path prefixes to v1beta1.ResourceAttribute records that must be granted to the user to continue. E.g. {\"/\":{\"resource\":\"pods\",\"namespace\":\"default\",\"name\":\"test\"}} only allows users who can see the pod test in namespace default.")
flagSet.String("openshift-service-account", "", "An optional name of an OpenShift service account to act as. If set, the injected service account info will be used to determine the client ID and client secret.")
Expand All @@ -98,15 +98,15 @@ func main() {
flagSet.String("approval-prompt", "force", "OAuth approval_prompt")

flagSet.String("signature-key", "", "GAP-Signature request signature key (algorithm:secretkey)")
flagSet.Var(&upstreamCAs, "upstream-ca", "paths to CA roots for the Upstream (target) Server (may be given multiple times, defaults to system trust store).")
flagSet.Var(upstreamCAs, "upstream-ca", "paths to CA roots for the Upstream (target) Server (may be given multiple times, defaults to system trust store).")

providerOpenShift := openshift.New()
providerOpenShift.Bind(flagSet)

flagSet.Parse(os.Args[1:])

providerOpenShift.SetClientCAFile(clientCA)
providerOpenShift.SetReviewCAs(openshiftCAs)
providerOpenShift.SetReviewCAs(openshiftCAs.Get().([]string))

if *showVersion {
fmt.Printf("oauth2_proxy v%s (built with %s)\n", VERSION, runtime.Version())
Expand Down
28 changes: 16 additions & 12 deletions providers/openshift/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

authenticationv1 "k8s.io/api/authentication/v1"
authorizationv1 "k8s.io/api/authorization/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authorization/authorizer"
Expand Down Expand Up @@ -319,11 +320,13 @@ func (p *OpenShiftProvider) Complete(data *providers.ProviderData, reviewURL *ur
// check whether we have access to perform authentication review
if authenticator.TokenAccessReviewClient != nil {
wait.PollImmediate(2*time.Second, 10*time.Second, func() (bool, error) {
_, err := authenticator.TokenAccessReviewClient.Create(&authenticationv1.TokenReview{
Spec: authenticationv1.TokenReviewSpec{
Token: "TEST",
_, err := authenticator.TokenAccessReviewClient.Create(context.TODO(),
&authenticationv1.TokenReview{
Spec: authenticationv1.TokenReviewSpec{
Token: "TEST",
},
},
})
metav1.CreateOptions{})
if err != nil {
log.Printf("unable to retrieve authentication information for tokens: %v", err)
return false, nil
Expand All @@ -339,15 +342,16 @@ func (p *OpenShiftProvider) Complete(data *providers.ProviderData, reviewURL *ur
// check whether we have access to perform authentication review
if authorizer.SubjectAccessReviewClient != nil {
wait.PollImmediate(2*time.Second, 10*time.Second, func() (bool, error) {
_, err := authorizer.SubjectAccessReviewClient.Create(&authorizationv1.SubjectAccessReview{
Spec: authorizationv1.SubjectAccessReviewSpec{
User: "TEST",
ResourceAttributes: &authorizationv1.ResourceAttributes{
Resource: "TEST",
Verb: "TEST",
_, err := authorizer.SubjectAccessReviewClient.Create(context.TODO(),
&authorizationv1.SubjectAccessReview{
Spec: authorizationv1.SubjectAccessReviewSpec{
User: "TEST",
ResourceAttributes: &authorizationv1.ResourceAttributes{
Resource: "TEST",
Verb: "TEST",
},
},
},
})
}, metav1.CreateOptions{})
if err != nil {
log.Printf("unable to retrieve authorization information for users: %v", err)
return false, nil
Expand Down
25 changes: 20 additions & 5 deletions string_array.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
package main

import (
"flag"
"strings"
)

type StringArray []string
var _ flag.Getter = StringArray{}

func (a *StringArray) Set(s string) error {
*a = append(*a, s)
type StringArray struct {
stringArray *[]string
}

func NewStringArray() *StringArray {
return &StringArray{
stringArray: &[]string{},
}
}

func (a StringArray) Get() interface{} {
return *a.stringArray
}

func (a StringArray) Set(s string) error {
*a.stringArray = append(*a.stringArray, s)
return nil
}

func (a *StringArray) String() string {
return strings.Join(*a, ",")
func (a StringArray) String() string {
return strings.Join(*a.stringArray, ",")
}
5 changes: 3 additions & 2 deletions string_array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package main

import (
"testing"

"github.com/bmizerany/assert"
)

func TestStringArray(t *testing.T) {
sa := StringArray{}
sa := NewStringArray()
assert.Equal(t, "", sa.String())
err := sa.Set("foo")
if err != nil {
Expand All @@ -18,4 +19,4 @@ func TestStringArray(t *testing.T) {
t.Errorf("unexpected error %v", err)
}
assert.Equal(t, "foo,bar", sa.String())
}
}
21 changes: 12 additions & 9 deletions test/e2e/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package e2e

import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"fmt"
Expand All @@ -21,6 +22,8 @@ import (
)

func TestOAuthProxyE2E(t *testing.T) {
testCtx := context.Background()

ns := os.Getenv("TEST_NAMESPACE")
oauthProxyTests := map[string]struct {
oauthProxyArgs []string
Expand Down Expand Up @@ -305,7 +308,7 @@ func TestOAuthProxyE2E(t *testing.T) {
continue
}
t.Run(fmt.Sprintf("setting up e2e tests %s", tcName), func(t *testing.T) {
_, err := kubeClientSet.CoreV1().ServiceAccounts(ns).Create(newOAuthProxySA())
_, err := kubeClientSet.CoreV1().ServiceAccounts(ns).Create(testCtx, newOAuthProxySA(), metav1.CreateOptions{})
if err != nil {
t.Fatalf("setup: error creating SA: %s", err)
}
Expand Down Expand Up @@ -333,18 +336,18 @@ func TestOAuthProxyE2E(t *testing.T) {
t.Fatalf("setup: error creating upstream TLS certs: %s", err)
}

_, err = kubeClientSet.CoreV1().Services(ns).Create(newOAuthProxyService())
_, err = kubeClientSet.CoreV1().Services(ns).Create(testCtx, newOAuthProxyService(), metav1.CreateOptions{})
if err != nil {
t.Fatalf("setup: error creating service: %s", err)
}

// configMap provides oauth-proxy with the certificates we created above
_, err = kubeClientSet.CoreV1().ConfigMaps(ns).Create(newOAuthProxyConfigMap(ns, caPem, serviceCert, serviceKey, upstreamCA, upstreamCert, upstreamKey))
_, err = kubeClientSet.CoreV1().ConfigMaps(ns).Create(testCtx, newOAuthProxyConfigMap(ns, caPem, serviceCert, serviceKey, upstreamCA, upstreamCert, upstreamKey), metav1.CreateOptions{})
if err != nil {
t.Fatalf("setup: error creating certificate configMap: %s", err)
}

oauthProxyPod, err := kubeClientSet.CoreV1().Pods(ns).Create(newOAuthProxyPod(image, backendImage, tc.oauthProxyArgs, tc.backendEnvs))
oauthProxyPod, err := kubeClientSet.CoreV1().Pods(ns).Create(testCtx, newOAuthProxyPod(image, backendImage, tc.oauthProxyArgs, tc.backendEnvs), metav1.CreateOptions{})
if err != nil {
t.Fatalf("setup: error creating oauth-proxy pod with image '%s' and args '%v': %s", image, tc.oauthProxyArgs, err)
}
Expand All @@ -355,7 +358,7 @@ func TestOAuthProxyE2E(t *testing.T) {
}

// Find the service CA for the client trust store
secrets, err := kubeClientSet.CoreV1().Secrets(ns).List(metav1.ListOptions{})
secrets, err := kubeClientSet.CoreV1().Secrets(ns).List(testCtx, metav1.ListOptions{})
if err != nil {
t.Fatalf("setup: error listing secrets: %s", err)
}
Expand Down Expand Up @@ -393,11 +396,11 @@ func TestOAuthProxyE2E(t *testing.T) {
t.Fatalf("skipping cleanup step for test '%s' and stopping on command", tcName)
}
t.Logf("cleaning up test %s", tcName)
kubeClientSet.CoreV1().Pods(ns).Delete("proxy", nil)
kubeClientSet.CoreV1().Services(ns).Delete("proxy", nil)
kubeClientSet.CoreV1().Pods(ns).Delete(testCtx, "proxy", metav1.DeleteOptions{})
kubeClientSet.CoreV1().Services(ns).Delete(testCtx, "proxy", metav1.DeleteOptions{})
deleteTestRoute("proxy-route", ns)
kubeClientSet.CoreV1().ConfigMaps(ns).Delete("proxy-certs", nil)
kubeClientSet.CoreV1().ServiceAccounts(ns).Delete("proxy", nil)
kubeClientSet.CoreV1().ConfigMaps(ns).Delete(testCtx, "proxy-certs", metav1.DeleteOptions{})
kubeClientSet.CoreV1().ServiceAccounts(ns).Delete(testCtx, "proxy", metav1.DeleteOptions{})
waitForPodDeletion(kubeClientSet, oauthProxyPod.Name, ns)
execCmd("oc", []string{"adm", "policy", "remove-role-from-user", "admin", user, "-n", ns}, "")
}()
Expand Down
7 changes: 4 additions & 3 deletions test/e2e/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package e2e
import (
"bufio"
"bytes"
"context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
Expand All @@ -22,12 +23,12 @@ import (

"golang.org/x/net/html"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
Expand Down Expand Up @@ -101,7 +102,7 @@ func waitForHealthzCheck(cas [][]byte, url string) error {

func podDeleted(c kubernetes.Interface, podName, namespace string) wait.ConditionFunc {
return func() (bool, error) {
_, err := c.CoreV1().Pods(namespace).Get(podName, metav1.GetOptions{})
_, err := c.CoreV1().Pods(namespace).Get(context.Background(), podName, metav1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return true, nil
Expand All @@ -114,7 +115,7 @@ func podDeleted(c kubernetes.Interface, podName, namespace string) wait.Conditio

func podRunning(c kubernetes.Interface, podName, namespace string) wait.ConditionFunc {
return func() (bool, error) {
pod, err := c.CoreV1().Pods(namespace).Get(podName, metav1.GetOptions{})
pod, err := c.CoreV1().Pods(namespace).Get(context.Background(), podName, metav1.GetOptions{})
if err != nil {
return false, err
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading