feat(oauth-proxy): configuration enhancements for k8s config (#1400)
* feat(oauth-proxy): configuration enhancements for k8s configpull/1410/head
parent
b2f337c978
commit
c364ba4e93
|
|
@ -286,6 +286,8 @@ func TestConvertFrom(t *testing.T) {
|
|||
IdentityProviderURL: "IdentityProviderURL",
|
||||
OAuthClientName: "OAuthClientName",
|
||||
OAuthSecret: "OAuthSecret",
|
||||
OAuthScope: "OAuthScope",
|
||||
IdentityToken: "IdentityToken",
|
||||
Gateway: chev2.Gateway{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
|
|
@ -377,6 +379,8 @@ func TestConvertFrom(t *testing.T) {
|
|||
assert.Equal(t, checlusterv1.Spec.Auth.IdentityProviderURL, "IdentityProviderURL")
|
||||
assert.Equal(t, checlusterv1.Spec.Auth.OAuthClientName, "OAuthClientName")
|
||||
assert.Equal(t, checlusterv1.Spec.Auth.OAuthSecret, "OAuthSecret")
|
||||
assert.Equal(t, checlusterv1.Spec.Auth.OAuthScope, "OAuthScope")
|
||||
assert.Equal(t, checlusterv1.Spec.Auth.IdentityToken, "IdentityToken")
|
||||
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresContainerResources.Limits.Cpu, "2")
|
||||
assert.Equal(t, checlusterv1.Spec.Database.ChePostgresContainerResources.Limits.Memory, "228Mi")
|
||||
|
|
|
|||
|
|
@ -245,6 +245,8 @@ func TestConvertTo(t *testing.T) {
|
|||
IdentityProviderURL: "IdentityProviderURL",
|
||||
OAuthClientName: "OAuthClientName",
|
||||
OAuthSecret: "OAuthSecret",
|
||||
OAuthScope: "OAuthScope",
|
||||
IdentityToken: "IdentityToken",
|
||||
GatewayAuthenticationSidecarImage: "GatewayAuthenticationSidecarImage",
|
||||
GatewayAuthorizationSidecarImage: "GatewayAuthorizationSidecarImage",
|
||||
},
|
||||
|
|
@ -304,6 +306,8 @@ func TestConvertTo(t *testing.T) {
|
|||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.IdentityProviderURL, "IdentityProviderURL")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.OAuthClientName, "OAuthClientName")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.OAuthSecret, "OAuthSecret")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.OAuthScope, "OAuthScope")
|
||||
assert.Equal(t, checlusterv2.Spec.Networking.Auth.IdentityToken, "IdentityToken")
|
||||
|
||||
assert.Equal(t, checlusterv2.Spec.ContainerRegistry.Hostname, "AirGapContainerRegistryHostname")
|
||||
assert.Equal(t, checlusterv2.Spec.ContainerRegistry.Organization, "AirGapContainerRegistryOrganization")
|
||||
|
|
|
|||
|
|
@ -265,6 +265,8 @@ func TestRoundConvertCheClusterV2(t *testing.T) {
|
|||
IdentityProviderURL: "IdentityProviderURL",
|
||||
OAuthClientName: "OAuthClientName",
|
||||
OAuthSecret: "OAuthSecret",
|
||||
OAuthScope: "OAuthScope",
|
||||
IdentityToken: "IdentityToken",
|
||||
Gateway: chev2.Gateway{
|
||||
Deployment: chev2.Deployment{
|
||||
Containers: []chev2.Container{
|
||||
|
|
@ -466,6 +468,8 @@ func TestRoundConvertCheClusterV1(t *testing.T) {
|
|||
IdentityProviderURL: "IdentityProviderURL",
|
||||
OAuthClientName: "OAuthClientName",
|
||||
OAuthSecret: "OAuthSecret",
|
||||
OAuthScope: "OAuthScope",
|
||||
IdentityToken: "IdentityToken",
|
||||
GatewayAuthenticationSidecarImage: "GatewayAuthenticationSidecarImage",
|
||||
GatewayAuthorizationSidecarImage: "GatewayAuthorizationSidecarImage",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -241,6 +241,8 @@ func (dst *CheCluster) convertFrom_Auth(src *chev2.CheCluster) error {
|
|||
dst.Spec.Auth.IdentityProviderURL = src.Spec.Networking.Auth.IdentityProviderURL
|
||||
dst.Spec.Auth.OAuthClientName = src.Spec.Networking.Auth.OAuthClientName
|
||||
dst.Spec.Auth.OAuthSecret = src.Spec.Networking.Auth.OAuthSecret
|
||||
dst.Spec.Auth.OAuthScope = src.Spec.Networking.Auth.OAuthScope
|
||||
dst.Spec.Auth.IdentityToken = src.Spec.Networking.Auth.IdentityToken
|
||||
|
||||
for _, c := range src.Spec.Networking.Auth.Gateway.Deployment.Containers {
|
||||
switch c.Name {
|
||||
|
|
|
|||
|
|
@ -182,6 +182,8 @@ func (src *CheCluster) convertTo_Networking_Auth(dst *chev2.CheCluster) error {
|
|||
dst.Spec.Networking.Auth.IdentityProviderURL = src.Spec.Auth.IdentityProviderURL
|
||||
dst.Spec.Networking.Auth.OAuthClientName = src.Spec.Auth.OAuthClientName
|
||||
dst.Spec.Networking.Auth.OAuthSecret = src.Spec.Auth.OAuthSecret
|
||||
dst.Spec.Networking.Auth.OAuthScope = src.Spec.Auth.OAuthScope
|
||||
dst.Spec.Networking.Auth.IdentityToken = src.Spec.Auth.IdentityToken
|
||||
|
||||
if err := src.convertTo_Networking_Auth_Gateway(dst); err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -499,6 +499,15 @@ type CheClusterSpecAuth struct {
|
|||
// Name of the secret set in the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OAuthClientName` field.
|
||||
// +optional
|
||||
OAuthSecret string `json:"oAuthSecret,omitempty"`
|
||||
// Access Token Scope.
|
||||
// This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
// +optional
|
||||
OAuthScope string `json:"oAuthScope,omitempty"`
|
||||
// Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`.
|
||||
// Default value is `id_token`.
|
||||
// This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
// +optional
|
||||
IdentityToken string `json:"identityToken,omitempty"`
|
||||
// Deprecated. The value of this flag is ignored.
|
||||
// Overrides the container image used in the Identity Provider, Keycloak or RH-SSO, deployment.
|
||||
// This includes the image tag. Omit it or leave it empty to use the default container image provided by the Operator.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
imagepullerv1alpha1 "github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1"
|
||||
|
|
@ -351,6 +354,16 @@ type Auth struct {
|
|||
OAuthClientName string `json:"oAuthClientName,omitempty"`
|
||||
// Name of the secret set in the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
OAuthSecret string `json:"oAuthSecret,omitempty"`
|
||||
// Access Token Scope.
|
||||
// This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
// +optional
|
||||
OAuthScope string `json:"oAuthScope,omitempty"`
|
||||
// Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`.
|
||||
// Default value is `id_token`.
|
||||
// This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
// +optional
|
||||
// +kubebuilder:validation:Enum=id_token;access_token
|
||||
IdentityToken string `json:"identityToken,omitempty"`
|
||||
// Gateway settings.
|
||||
// +optional
|
||||
Gateway Gateway `json:"gateway,omitempty"`
|
||||
|
|
@ -631,3 +644,18 @@ func (c *CheCluster) GetDefaultNamespace() string {
|
|||
|
||||
return "<username>-" + os.Getenv("CHE_FLAVOR")
|
||||
}
|
||||
|
||||
func (c *CheCluster) GetIdentityToken() string {
|
||||
if len(c.Spec.Networking.Auth.IdentityToken) > 0 {
|
||||
return c.Spec.Networking.Auth.IdentityToken
|
||||
}
|
||||
|
||||
if infrastructure.IsOpenShift() {
|
||||
return constants.AccessToken
|
||||
}
|
||||
return constants.IdToken
|
||||
}
|
||||
|
||||
func (c *CheCluster) IsAccessTokenConfigured() bool {
|
||||
return c.GetIdentityToken() == constants.AccessToken
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
package v2
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIsAccesTokenConfigured(t *testing.T) {
|
||||
t.Run("TestIsAccesTokenConfigured when access_token defined", func(t *testing.T) {
|
||||
cheCluster := &CheCluster{
|
||||
Spec: CheClusterSpec{
|
||||
Networking: CheClusterSpecNetworking{
|
||||
Auth: Auth{
|
||||
IdentityToken: "access_token",
|
||||
},
|
||||
}},
|
||||
}
|
||||
assert.True(t, cheCluster.IsAccessTokenConfigured(), "'access_token' should be activated")
|
||||
})
|
||||
t.Run("TestIsAccesTokenConfigured when id_token defined", func(t *testing.T) {
|
||||
cheCluster := &CheCluster{
|
||||
Spec: CheClusterSpec{
|
||||
Networking: CheClusterSpecNetworking{
|
||||
Auth: Auth{
|
||||
IdentityToken: "id_token",
|
||||
},
|
||||
}},
|
||||
}
|
||||
assert.False(t, cheCluster.IsAccessTokenConfigured(), "'access_token' should not be activated")
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetIdentityToken(t *testing.T) {
|
||||
t.Run("TestGetIdentityToken when access_token defined in config and k8s", func(t *testing.T) {
|
||||
cheCluster := &CheCluster{
|
||||
Spec: CheClusterSpec{
|
||||
Networking: CheClusterSpecNetworking{
|
||||
Auth: Auth{
|
||||
IdentityToken: "access_token",
|
||||
},
|
||||
}},
|
||||
}
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
assert.Equal(t, "access_token", cheCluster.GetIdentityToken(),
|
||||
"'access_token' should be used")
|
||||
})
|
||||
|
||||
t.Run("TestGetIdentityToken when id_token defined in config and k8s", func(t *testing.T) {
|
||||
cheCluster := &CheCluster{
|
||||
Spec: CheClusterSpec{
|
||||
Networking: CheClusterSpecNetworking{
|
||||
Auth: Auth{
|
||||
IdentityToken: "id_token",
|
||||
},
|
||||
}},
|
||||
}
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
assert.Equal(t, "id_token", cheCluster.GetIdentityToken(),
|
||||
"'id_token' should be used")
|
||||
})
|
||||
|
||||
t.Run("TestGetIdentityToken when no defined token in config and k8s", func(t *testing.T) {
|
||||
cheCluster := &CheCluster{
|
||||
Spec: CheClusterSpec{
|
||||
Networking: CheClusterSpecNetworking{
|
||||
Auth: Auth{},
|
||||
}},
|
||||
}
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
assert.Equal(t, "id_token", cheCluster.GetIdentityToken(),
|
||||
"'id_token' should be used")
|
||||
})
|
||||
|
||||
t.Run("TestGetIdentityToken when access_token defined in config and openshift", func(t *testing.T) {
|
||||
cheCluster := &CheCluster{
|
||||
Spec: CheClusterSpec{
|
||||
Networking: CheClusterSpecNetworking{
|
||||
Auth: Auth{
|
||||
IdentityToken: "access_token",
|
||||
},
|
||||
}},
|
||||
}
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
|
||||
assert.Equal(t, "access_token", cheCluster.GetIdentityToken(),
|
||||
"'access_token' should be used")
|
||||
})
|
||||
|
||||
t.Run("TestGetIdentityToken when id_token defined in config and openshift", func(t *testing.T) {
|
||||
cheCluster := &CheCluster{
|
||||
Spec: CheClusterSpec{
|
||||
Networking: CheClusterSpecNetworking{
|
||||
Auth: Auth{
|
||||
IdentityToken: "id_token",
|
||||
},
|
||||
}},
|
||||
}
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
|
||||
assert.Equal(t, "id_token", cheCluster.GetIdentityToken(),
|
||||
"'id_token' should be used")
|
||||
})
|
||||
|
||||
t.Run("TestGetIdentityToken when no defined token in config and openshift", func(t *testing.T) {
|
||||
cheCluster := &CheCluster{
|
||||
Spec: CheClusterSpec{
|
||||
Networking: CheClusterSpecNetworking{
|
||||
Auth: Auth{},
|
||||
}},
|
||||
}
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
|
||||
assert.Equal(t, "access_token", cheCluster.GetIdentityToken(),
|
||||
"'access_token' should be used")
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestGetDefaultIdentityToken(t *testing.T) {
|
||||
emptyCheCluster := CheCluster{}
|
||||
|
||||
var tests = []struct {
|
||||
infrastructure infrastructure.Type
|
||||
identityToken string
|
||||
}{
|
||||
{infrastructure.OpenShiftv4, "access_token"},
|
||||
{infrastructure.Kubernetes, "id_token"},
|
||||
{infrastructure.Unsupported, "id_token"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
infrastructure.InitializeForTesting(test.infrastructure)
|
||||
if actual := emptyCheCluster.GetIdentityToken(); !reflect.DeepEqual(test.identityToken, actual) {
|
||||
t.Errorf("Test Failed. Expected '%s', but got '%s'", test.identityToken, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -256,6 +256,12 @@ spec:
|
|||
field. By default, this will be automatically calculated and
|
||||
set by the Operator.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There
|
||||
are two types of tokens supported: `id_token` and `access_token`.
|
||||
Default value is `id_token`. This field is specific to Che
|
||||
installations made for Kubernetes only and ignored for OpenShift.'
|
||||
type: string
|
||||
initialOpenShiftOAuthUser:
|
||||
description: Deprecated. The value of this flag is ignored.
|
||||
For operating with the OpenShift OAuth authentication, create
|
||||
|
|
@ -279,6 +285,10 @@ spec:
|
|||
to setup identity federation on the OpenShift side. Auto-generated
|
||||
when left blank. See also the `OpenShiftoAuth` field.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che
|
||||
installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient`
|
||||
resource used to setup identity federation on the OpenShift
|
||||
|
|
@ -2287,10 +2297,25 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There
|
||||
are two types of tokens supported: `id_token` and `access_token`.
|
||||
Default value is `id_token`. This field is specific to
|
||||
Che installations made for Kubernetes only and ignored
|
||||
for OpenShift.'
|
||||
enum:
|
||||
- id_token
|
||||
- access_token
|
||||
type: string
|
||||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource
|
||||
used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific
|
||||
to Che installations made for Kubernetes only and ignored
|
||||
for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient`
|
||||
resource used to set up identity federation on the OpenShift
|
||||
|
|
|
|||
|
|
@ -234,6 +234,12 @@ spec:
|
|||
By default, this will be automatically calculated and set by
|
||||
the Operator.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are
|
||||
two types of tokens supported: `id_token` and `access_token`.
|
||||
Default value is `id_token`. This field is specific to Che installations
|
||||
made for Kubernetes only and ignored for OpenShift.'
|
||||
type: string
|
||||
initialOpenShiftOAuthUser:
|
||||
description: Deprecated. The value of this flag is ignored. For
|
||||
operating with the OpenShift OAuth authentication, create a
|
||||
|
|
@ -257,6 +263,10 @@ spec:
|
|||
to setup identity federation on the OpenShift side. Auto-generated
|
||||
when left blank. See also the `OpenShiftoAuth` field.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che
|
||||
installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient`
|
||||
resource used to setup identity federation on the OpenShift
|
||||
|
|
@ -2232,10 +2242,24 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There
|
||||
are two types of tokens supported: `id_token` and `access_token`.
|
||||
Default value is `id_token`. This field is specific to Che
|
||||
installations made for Kubernetes only and ignored for OpenShift.'
|
||||
enum:
|
||||
- id_token
|
||||
- access_token
|
||||
type: string
|
||||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource
|
||||
used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to
|
||||
Che installations made for Kubernetes only and ignored for
|
||||
OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient`
|
||||
resource used to set up identity federation on the OpenShift
|
||||
|
|
|
|||
|
|
@ -475,9 +475,7 @@ func provisionMainWorkspaceRoute(cheCluster *chev2.CheCluster, routing *dwo.DevW
|
|||
getServiceURL(wsGatewayPort, dwId, dwNamespace),
|
||||
[]string{"/" + dwId})
|
||||
|
||||
if infrastructure.IsOpenShift() {
|
||||
// on OpenShift, we need to set authorization header.
|
||||
// This MUST come before Auth, because Auth needs Authorization header to be properly set.
|
||||
if cheCluster.IsAccessTokenConfigured() {
|
||||
cfg.AddAuthHeaderRewrite(dwId)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -161,6 +161,9 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server (Keycloak / RH-SSO server). Set this ONLY when a use of an external Identity Provider is needed. See the `externalIdentityProvider` field. By default, this will be automatically calculated and set by the Operator.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
type: string
|
||||
initialOpenShiftOAuthUser:
|
||||
description: Deprecated. The value of this flag is ignored. For operating with the OpenShift OAuth authentication, create a new user account since the kubeadmin can not be used. If the value is true, then a new OpenShift OAuth user will be created for the HTPasswd identity provider. If the value is false and the user has already been created, then it will be removed. If value is an empty, then do nothing. The user's credentials are stored in the `openshift-oauth-user-credentials` secret in 'openshift-config' namespace by Operator. Note that this solution is Openshift 4 platform-specific.
|
||||
type: boolean
|
||||
|
|
@ -170,6 +173,9 @@ spec:
|
|||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OpenShiftoAuth` field.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OAuthClientName` field.
|
||||
type: string
|
||||
|
|
@ -1581,9 +1587,18 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
enum:
|
||||
- id_token
|
||||
- access_token
|
||||
type: string
|
||||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -156,6 +156,9 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server (Keycloak / RH-SSO server). Set this ONLY when a use of an external Identity Provider is needed. See the `externalIdentityProvider` field. By default, this will be automatically calculated and set by the Operator.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
type: string
|
||||
initialOpenShiftOAuthUser:
|
||||
description: Deprecated. The value of this flag is ignored. For operating with the OpenShift OAuth authentication, create a new user account since the kubeadmin can not be used. If the value is true, then a new OpenShift OAuth user will be created for the HTPasswd identity provider. If the value is false and the user has already been created, then it will be removed. If value is an empty, then do nothing. The user's credentials are stored in the `openshift-oauth-user-credentials` secret in 'openshift-config' namespace by Operator. Note that this solution is Openshift 4 platform-specific.
|
||||
type: boolean
|
||||
|
|
@ -165,6 +168,9 @@ spec:
|
|||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OpenShiftoAuth` field.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OAuthClientName` field.
|
||||
type: string
|
||||
|
|
@ -1576,9 +1582,18 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
enum:
|
||||
- id_token
|
||||
- access_token
|
||||
type: string
|
||||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -161,6 +161,9 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server (Keycloak / RH-SSO server). Set this ONLY when a use of an external Identity Provider is needed. See the `externalIdentityProvider` field. By default, this will be automatically calculated and set by the Operator.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
type: string
|
||||
initialOpenShiftOAuthUser:
|
||||
description: Deprecated. The value of this flag is ignored. For operating with the OpenShift OAuth authentication, create a new user account since the kubeadmin can not be used. If the value is true, then a new OpenShift OAuth user will be created for the HTPasswd identity provider. If the value is false and the user has already been created, then it will be removed. If value is an empty, then do nothing. The user's credentials are stored in the `openshift-oauth-user-credentials` secret in 'openshift-config' namespace by Operator. Note that this solution is Openshift 4 platform-specific.
|
||||
type: boolean
|
||||
|
|
@ -170,6 +173,9 @@ spec:
|
|||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OpenShiftoAuth` field.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OAuthClientName` field.
|
||||
type: string
|
||||
|
|
@ -1581,9 +1587,18 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
enum:
|
||||
- id_token
|
||||
- access_token
|
||||
type: string
|
||||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -156,6 +156,9 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server (Keycloak / RH-SSO server). Set this ONLY when a use of an external Identity Provider is needed. See the `externalIdentityProvider` field. By default, this will be automatically calculated and set by the Operator.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
type: string
|
||||
initialOpenShiftOAuthUser:
|
||||
description: Deprecated. The value of this flag is ignored. For operating with the OpenShift OAuth authentication, create a new user account since the kubeadmin can not be used. If the value is true, then a new OpenShift OAuth user will be created for the HTPasswd identity provider. If the value is false and the user has already been created, then it will be removed. If value is an empty, then do nothing. The user's credentials are stored in the `openshift-oauth-user-credentials` secret in 'openshift-config' namespace by Operator. Note that this solution is Openshift 4 platform-specific.
|
||||
type: boolean
|
||||
|
|
@ -165,6 +168,9 @@ spec:
|
|||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OpenShiftoAuth` field.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OAuthClientName` field.
|
||||
type: string
|
||||
|
|
@ -1576,9 +1582,18 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
enum:
|
||||
- id_token
|
||||
- access_token
|
||||
type: string
|
||||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -156,6 +156,9 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server (Keycloak / RH-SSO server). Set this ONLY when a use of an external Identity Provider is needed. See the `externalIdentityProvider` field. By default, this will be automatically calculated and set by the Operator.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
type: string
|
||||
initialOpenShiftOAuthUser:
|
||||
description: Deprecated. The value of this flag is ignored. For operating with the OpenShift OAuth authentication, create a new user account since the kubeadmin can not be used. If the value is true, then a new OpenShift OAuth user will be created for the HTPasswd identity provider. If the value is false and the user has already been created, then it will be removed. If value is an empty, then do nothing. The user's credentials are stored in the `openshift-oauth-user-credentials` secret in 'openshift-config' namespace by Operator. Note that this solution is Openshift 4 platform-specific.
|
||||
type: boolean
|
||||
|
|
@ -165,6 +168,9 @@ spec:
|
|||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OpenShiftoAuth` field.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to setup identity federation on the OpenShift side. Auto-generated when left blank. See also the `OAuthClientName` field.
|
||||
type: string
|
||||
|
|
@ -1576,9 +1582,18 @@ spec:
|
|||
identityProviderURL:
|
||||
description: Public URL of the Identity Provider server.
|
||||
type: string
|
||||
identityToken:
|
||||
description: 'Identity token to be passed to upstream. There are two types of tokens supported: `id_token` and `access_token`. Default value is `id_token`. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.'
|
||||
enum:
|
||||
- id_token
|
||||
- access_token
|
||||
type: string
|
||||
oAuthClientName:
|
||||
description: Name of the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
oAuthScope:
|
||||
description: Access Token Scope. This field is specific to Che installations made for Kubernetes only and ignored for OpenShift.
|
||||
type: string
|
||||
oAuthSecret:
|
||||
description: Name of the secret set in the OpenShift `OAuthClient` resource used to set up identity federation on the OpenShift side.
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ const (
|
|||
GitLabOAuthConfigClientIdFileName = "id"
|
||||
GitLabOAuthConfigClientSecretFileName = "secret"
|
||||
OAuthScmConfiguration = "oauth-scm-configuration"
|
||||
AccessToken = "access_token"
|
||||
IdToken = "id_token"
|
||||
|
||||
// Labels
|
||||
KubernetesComponentLabelKey = "app.kubernetes.io/component"
|
||||
|
|
|
|||
|
|
@ -259,3 +259,13 @@ func FormatLabels(m map[string]string) string {
|
|||
|
||||
return labels.FormatLabels(m)
|
||||
}
|
||||
|
||||
// Whitelists the host.
|
||||
// Sample: Whitelist("che.yourcompany.com") -> ".yourcompany.com"
|
||||
func Whitelist(hostname string) (value string) {
|
||||
i := strings.Index(hostname, ".")
|
||||
if i > -1 {
|
||||
return hostname[i:]
|
||||
}
|
||||
return hostname
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,3 +63,21 @@ func TestGetImageNameAndTag(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWhitelist(t *testing.T) {
|
||||
var tests = []struct {
|
||||
host string
|
||||
whitelistedHost string
|
||||
}{
|
||||
{"che.qwruwqlrj.com", ".qwruwqlrj.com"},
|
||||
{"one.two.three.four", ".two.three.four"},
|
||||
{"abraCadabra-KvakaZybra", "abraCadabra-KvakaZybra"},
|
||||
{".", "."},
|
||||
{"", ""},
|
||||
}
|
||||
for _, test := range tests {
|
||||
if actual := Whitelist(test.host); !reflect.DeepEqual(test.whitelistedHost, actual) {
|
||||
t.Errorf("Test Failed. Expected '%s', but got '%s'", test.whitelistedHost, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import (
|
|||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
|
|
@ -126,7 +125,7 @@ func (d *DashboardReconciler) createGatewayConfig(ctx *chetypes.DeployContext) *
|
|||
10,
|
||||
"http://"+d.getComponentName(ctx)+":8080",
|
||||
[]string{})
|
||||
if infrastructure.IsOpenShift() {
|
||||
if ctx.CheCluster.IsAccessTokenConfigured() {
|
||||
cfg.AddAuthHeaderRewrite(d.getComponentName(ctx))
|
||||
}
|
||||
return cfg
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ func syncAll(deployContext *chetypes.DeployContext) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if infrastructure.IsOpenShift() {
|
||||
if instance.IsAccessTokenConfigured() {
|
||||
if headerRewritePluginConfig, err := getGatewayHeaderRewritePluginConfigSpec(instance); err == nil {
|
||||
if _, err := deploy.Sync(deployContext, headerRewritePluginConfig, configMapDiffOpts); err != nil {
|
||||
return err
|
||||
|
|
@ -238,8 +238,10 @@ func getGatewayServerConfigSpec(deployContext *chetypes.DeployContext) (corev1.C
|
|||
"http://"+deploy.CheServiceName+":8080",
|
||||
[]string{})
|
||||
|
||||
if infrastructure.IsOpenShift() {
|
||||
if deployContext.CheCluster.IsAccessTokenConfigured() {
|
||||
cfg.AddAuthHeaderRewrite(serverComponentName)
|
||||
}
|
||||
if infrastructure.IsOpenShift() {
|
||||
// native user mode is currently only available on OpenShift but let's be defensive here so that
|
||||
// this doesn't break once we enable it on Kubernetes, too. Token check will have to work
|
||||
// differently on Kuberentes.
|
||||
|
|
@ -398,7 +400,7 @@ providers:
|
|||
log:
|
||||
level: "INFO"`, traefikPort)
|
||||
|
||||
if infrastructure.IsOpenShift() {
|
||||
if instance.IsAccessTokenConfigured() {
|
||||
data += `
|
||||
experimental:
|
||||
localPlugins:
|
||||
|
|
@ -546,7 +548,7 @@ func getTraefikContainerVolumeMounts(instance *chev2.CheCluster) []corev1.Volume
|
|||
MountPath: "/dynamic-config",
|
||||
},
|
||||
}
|
||||
if infrastructure.IsOpenShift() {
|
||||
if instance.IsAccessTokenConfigured() {
|
||||
mounts = append(mounts, corev1.VolumeMount{
|
||||
Name: "header-rewrite-traefik-plugin",
|
||||
MountPath: "/plugins-local/src/github.com/che-incubator/header-rewrite-traefik-plugin",
|
||||
|
|
@ -580,7 +582,7 @@ func getVolumesSpec(instance *chev2.CheCluster) []corev1.Volume {
|
|||
getOauthProxyConfigVolume(),
|
||||
getKubeRbacProxyConfigVolume())
|
||||
|
||||
if infrastructure.IsOpenShift() {
|
||||
if instance.IsAccessTokenConfigured() {
|
||||
volumes = append(volumes, corev1.Volume{
|
||||
Name: "header-rewrite-traefik-plugin",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/utils"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
@ -114,8 +115,11 @@ cookie_secret = "%s"
|
|||
cookie_expire = "24h0m0s"
|
||||
email_domains = "*"
|
||||
cookie_httponly = false
|
||||
pass_authorization_header = true
|
||||
skip_provider_button = true
|
||||
whitelist_domains = "%s"
|
||||
cookie_domains = "%s"
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
`, GatewayServicePort,
|
||||
ctx.CheHost,
|
||||
|
|
@ -123,7 +127,11 @@ skip_provider_button = true
|
|||
ctx.CheCluster.Spec.Networking.Auth.OAuthClientName,
|
||||
ctx.CheCluster.Spec.Networking.Auth.OAuthSecret,
|
||||
cookieSecret,
|
||||
skipAuthConfig(ctx.CheCluster))
|
||||
utils.Whitelist(ctx.CheHost),
|
||||
utils.Whitelist(ctx.CheHost),
|
||||
skipAuthConfig(ctx.CheCluster),
|
||||
identityTokenConfig(ctx.CheCluster),
|
||||
oauthScopeConfig(ctx.CheCluster))
|
||||
}
|
||||
|
||||
func skipAuthConfig(instance *chev2.CheCluster) string {
|
||||
|
|
@ -147,6 +155,23 @@ func skipAuthConfig(instance *chev2.CheCluster) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func identityTokenConfig(instance *chev2.CheCluster) string {
|
||||
if instance.IsAccessTokenConfigured() {
|
||||
// pass OAuth access_token to upstream via X-Forwarded-Access-Token header
|
||||
return "pass_access_token = true"
|
||||
}
|
||||
// pass OIDC IDToken to upstream via Authorization Bearer header
|
||||
return "pass_authorization_header = true"
|
||||
}
|
||||
|
||||
func oauthScopeConfig(instance *chev2.CheCluster) string {
|
||||
scope := instance.Spec.Networking.Auth.OAuthScope
|
||||
if len(scope) > 1 {
|
||||
return fmt.Sprintf("scope = \"%s\"", scope)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getOauthProxyContainerSpec(ctx *chetypes.DeployContext) corev1.Container {
|
||||
// append env var with ConfigMap revision to restore pod automatically when config has been changed
|
||||
cm := &corev1.ConfigMap{}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
//
|
||||
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||
// This program and the accompanying materials are made
|
||||
// available under the terms of the Eclipse Public License 2.0
|
||||
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0
|
||||
//
|
||||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
package gateway
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestKubernetesOauthProxyConfig(t *testing.T) {
|
||||
ctx := test.GetDeployContext(
|
||||
&chev2.CheCluster{
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Auth: chev2.Auth{
|
||||
IdentityProviderURL: "http://bla.bla.bla/idp",
|
||||
OAuthClientName: "client name",
|
||||
OAuthSecret: "secret",
|
||||
},
|
||||
}},
|
||||
}, nil)
|
||||
ctx.CheHost = "che-site.che-domain.com"
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
config := kubernetesOauthProxyConfig(ctx, "blabol")
|
||||
assert.Contains(t, config, "pass_authorization_header = true")
|
||||
assert.Contains(t, config, "whitelist_domains = \".che-domain.com\"")
|
||||
assert.Contains(t, config, "cookie_domains = \".che-domain.com\"")
|
||||
assert.NotContains(t, config, "scope = ")
|
||||
assert.NotContains(t, config, "pass_access_token = true")
|
||||
}
|
||||
|
||||
func TestScopeDefinedForKubernetesOauthProxyConfig(t *testing.T) {
|
||||
ctx := test.GetDeployContext(
|
||||
&chev2.CheCluster{
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Auth: chev2.Auth{
|
||||
IdentityProviderURL: "http://bla.bla.bla/idp",
|
||||
OAuthClientName: "client name",
|
||||
OAuthSecret: "secret",
|
||||
OAuthScope: "scope1 scope2 scope3 scope4 scope5",
|
||||
},
|
||||
}},
|
||||
}, nil)
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
config := kubernetesOauthProxyConfig(ctx, "blabol")
|
||||
assert.Contains(t, config, "scope = \"scope1 scope2 scope3 scope4 scope5\"")
|
||||
}
|
||||
|
||||
func TestAccessTokenDefinedForKubernetesOauthProxyConfig(t *testing.T) {
|
||||
ctx := test.GetDeployContext(
|
||||
&chev2.CheCluster{
|
||||
Spec: chev2.CheClusterSpec{
|
||||
Networking: chev2.CheClusterSpecNetworking{
|
||||
Auth: chev2.Auth{
|
||||
IdentityProviderURL: "http://bla.bla.bla/idp",
|
||||
OAuthClientName: "client name",
|
||||
OAuthSecret: "secret",
|
||||
IdentityToken: "access_token",
|
||||
},
|
||||
}},
|
||||
}, nil)
|
||||
infrastructure.InitializeForTesting(infrastructure.Kubernetes)
|
||||
|
||||
config := kubernetesOauthProxyConfig(ctx, "blabol")
|
||||
assert.Contains(t, config, "pass_access_token = true")
|
||||
assert.NotContains(t, config, "pass_authorization_header = true")
|
||||
}
|
||||
Loading…
Reference in New Issue