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
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions Dockerfile.rhel7
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ COPY manifests /manifests/
COPY quickstarts/*.yaml /manifests/

# extensions manifests generated from openshift/api types
COPY vendor/github.com/openshift/api/console/v1/*.crd.yaml /manifests/
COPY vendor/github.com/openshift/api/operator/*/*console-operator*.crd.yaml /manifests/
COPY vendor/github.com/openshift/api/helm/*/*crd.yaml /manifests/
COPY vendor/github.com/openshift/api/console/v1/zz_generated.crd-manifests/*.crd.yaml /manifests/
COPY vendor/github.com/openshift/api/operator/*/zz_generated.crd-manifests/*console*.crd.yaml /manifests/
COPY vendor/github.com/openshift/api/helm/*/zz_generated.crd-manifests/*crd.yaml /manifests/

LABEL io.k8s.display-name="OpenShift console-operator" \
io.k8s.description="This is a component of OpenShift Container Platform and manages the lifecycle of the web console." \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ docker build -t <registry>/<your-username>/console-operator:<version> .
# following: docker.io/openshift/origin-console-operator:latest
# for development, you are going to push to an alternate registry.
# specifically it can look something like this:
docker build -t quay.io/benjaminapetersen/console-operator:latest .
docker build -f Dockerfile.rhel7 -t quay.io/benjaminapetersen/console-operator:latest .
```
You can optionally build a specific version.

Expand Down
20 changes: 20 additions & 0 deletions bindata/assets/services/console-nodeport-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# This 'console' service manifest is used when the ingress cluster capability is disabled.
# Service will be exposed using a NodePort to enable the alternative ingress.
apiVersion: v1
kind: Service
metadata:
name: console
namespace: openshift-console
labels:
app: console
spec:
ports:
- name: https
protocol: TCP
port: 443
targetPort: 8443
selector:
app: console
component: ui
type: NodePort
sessionAffinity: None
18 changes: 18 additions & 0 deletions bindata/assets/services/downloads-nodeport-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This 'downloads' service manifest is used when the ingress cluster capability is disabled.
# Service will be exposed using a NodePort to enable the alternative ingress.
apiVersion: v1
kind: Service
metadata:
namespace: openshift-console
name: downloads
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
selector:
app: console
component: downloads
type: NodePort
sessionAffinity: None
132 changes: 132 additions & 0 deletions docs/alb-ingress-rosa-hcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Use AWS ALB as alternative ingress on ROSA HCP

This doc aims at showing the effort needed to expose the OpenShift console via AWS ALB on a ROSA HCP cluster.
The use case in mind is [HyperShift hosted clusters where the Ingress capability is disabled](https://github.com/openshift/enhancements/pull/1415).

## Requirements

- ROSA HCP OpenShift cluster.
- [AWS Load Balancer Operator installed and its controller created](https://docs.openshift.com/rosa/networking/aws-load-balancer-operator.html).
- User logged as a cluster admin.

## Procedure

### Create certificate in AWS Certificate Manager

In order to configure an HTTPS listener on AWS ALB you need to have a certificate created in AWS Certificate Manager.
You can import an existing certificate or request a new one. Make sure the certificate is created in the same region as your cluster.
Note the certificate ARN and the DNS name used in the certificate, you will need it later.

### Create Ingress resources for the NodePort services

To provision ALBs create the following resources:
```bash
cat <<EOF | oc apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: instance
alb.ingress.kubernetes.io/backend-protocol: HTTPS
alb.ingress.kubernetes.io/certificate-arn: ${CERTIFICATE_ARN}
name: console
namespace: openshift-console
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: console
port:
number: 443
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: instance
alb.ingress.kubernetes.io/backend-protocol: HTTP
alb.ingress.kubernetes.io/certificate-arn: ${CERTIFICATE_ARN}
name: downloads
namespace: openshift-console
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: downloads
port:
number: 80
EOF
```

### Update console config

Once the console ALBs are ready you need to let the console operator know which urls to use.

#### Add custom trusted CA (optional)

To add the CA of the certificates used in the ingress objects to [the trusted bundle of the OpenShift cluster](https://docs.openshift.com/container-platform/latest/networking/configuring-a-custom-pki.html#nw-proxy-configure-object_configuring-a-custom-pki), follow these steps:
```bash
$ oc -n openshift-config create configmap console-ca-bundle --from-file=ca-bundle.crt=/path/to/pemencoded/cacert
$ oc patch proxy cluster --type=merge -p '{"spec":{"trustedCA":{"name":"console-ca-bundle"}}}'
```

#### Setup DNS (optional)

The console ALBs have public DNS names that might not match the Subject Alternative Name (SAN) from the certificates. Ensure public DNS records matching the certificates' SANs are created and target the following hostnames:
```bash
$ oc -n openshift-console get ing console -o yaml | yq .status.loadBalancer.ingress[0].hostname
k8s-openshif-console-xxxxxxxxxx-xxxxxxxx.us-east-2.elb.amazonaws.comdd
$ oc -n openshift-console get ing downloads -o yaml | yq .status.loadBalancer.ingress[0].hostname
k8s-openshif-download-xxxxxxxxxx-xxxxxxxxxx.us-east-2.elb.amazonaws.com
```

#### Update console operator config

Update the console operator config providing the custom urls:
```bash
$ oc patch console.operator.openshift.io cluster --type=merge -p "{\"spec\":{\"ingress\":{\"consoleURL\":\"https://${CONSOLE_HOST}\",\"clientDownloadsURL\":\"https://${DOWNLOADS_HOST}\"}}}"
```
**Note**: ensure that the hosts used in the urls match the SAN from the corresponding certificates.

## Notes

1. ROSA HCP does not have the authentication operator, the authentication server is managed centrally by the HyperShift layer:
```bash
$ oc -n openshift-authentication-operator get deploy,route
No resources found

$ oc -n openshift-authentication get pods,routes
No resources found

$ oc get oauthclient | grep -v console
NAME SECRET WWW-CHALLENGE TOKEN-MAX-AGE REDIRECT URIS
openshift-browser-client false default https://oauth.mytestcluster.5199.s3.devshift.org:443/oauth/token/display
openshift-challenging-client true default https://oauth.mytestcluster.5199.s3.devshift.org:443/oauth/token/implicit

$ oc -n openshift-console rsh deploy/console curl -k https://openshift.default.svc/.well-known/oauth-authorization-server
{
"issuer": "https://oauth.mytestcluster.5199.s3.devshift.org:443",
"authorization_endpoint": "https://oauth.mytestcluster.5199.s3.devshift.org:443/oauth/authorize",
"token_endpoint": "https://oauth.mytestcluster.5199.s3.devshift.org:443/oauth/token",
```

2. When the ingress capability is disabled, the console operator relies on the end user to provide the console and download URLs (using the operator API) for health checks and oauthclient.

3. When the ingress capability is disabled, the console operator skips the implementation of the component route customization.

4. To simulate the absence of ingress connectivity when the ingress capability is disabled, set the desired replicas to zero in the default ingress controller:
```bash
$ oc -n openshift-ingress-operator patch ingresscontroller default --type='json' -p='[{"op": "replace", "path": "/spec/replicas", "value":0}]'
```
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/go-test/deep v1.0.5
github.com/google/go-cmp v0.6.0
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822
github.com/openshift/api v0.0.0-20231218131639-7a5aa77cc72d
github.com/openshift/api v0.0.0-20240702171116-4b89b3a92a17
github.com/openshift/build-machinery-go v0.0.0-20220913142420-e25cf57ea46d
github.com/openshift/client-go v0.0.0-20231218140158-47f6d749b9d9
github.com/openshift/library-go v0.0.0-20240124134907-4dfbf6bc7b11
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/openshift/api v0.0.0-20231218131639-7a5aa77cc72d h1:aVjDasSo08KUIltX++Mcl6ptN0ooxh3dRttHBFGVVI0=
github.com/openshift/api v0.0.0-20231218131639-7a5aa77cc72d/go.mod h1:RLaNkRn87bQeH3MpTWXCxlSb62qVGBxfQY344jBfVsg=
github.com/openshift/api v0.0.0-20240702171116-4b89b3a92a17 h1:Hl43oJR6bKPkW8xQty+N+/Ot8ioEyLwNU4CNvxik7iE=
github.com/openshift/api v0.0.0-20240702171116-4b89b3a92a17/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
github.com/openshift/build-machinery-go v0.0.0-20220913142420-e25cf57ea46d h1:RR4ah7FfaPR1WePizm0jlrsbmPu91xQZnAsVVreQV1k=
github.com/openshift/build-machinery-go v0.0.0-20220913142420-e25cf57ea46d/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE=
github.com/openshift/client-go v0.0.0-20231218140158-47f6d749b9d9 h1:kjgW3luAkf9NWu+8u+jqNNbexDG+CY82/INw8hGbG14=
Expand Down
16 changes: 16 additions & 0 deletions manifests/06-trusted-ca-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# The network operator is responsible for injecting
# the trusted ca bundle into this configmap.
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
capability.openshift.io/name: Console
include.release.openshift.io/hypershift: "true"
include.release.openshift.io/ibm-cloud-managed: "true"
include.release.openshift.io/self-managed-high-availability: "true"
include.release.openshift.io/single-node-developer: "true"
release.openshift.io/create-only: "true"
labels:
config.openshift.io/inject-trusted-cabundle: "true"
name: trusted-ca
namespace: openshift-console-operator
8 changes: 8 additions & 0 deletions manifests/07-operator-ibm-cloud-managed.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ spec:
name: config
- mountPath: /var/run/secrets/serving-cert
name: serving-cert
- mountPath: /etc/pki/ca-trust/extracted/pem
name: trusted-ca
priorityClassName: system-cluster-critical
securityContext:
runAsNonRoot: true
Expand All @@ -97,3 +99,9 @@ spec:
secret:
optional: true
secretName: serving-cert
- configMap:
items:
- key: ca-bundle.crt
path: tls-ca-bundle.pem
name: trusted-ca
name: trusted-ca
8 changes: 8 additions & 0 deletions manifests/07-operator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ spec:
name: config
- mountPath: /var/run/secrets/serving-cert
name: serving-cert
- mountPath: /etc/pki/ca-trust/extracted/pem
name: trusted-ca
env:
- name: CONSOLE_IMAGE
value: registry.svc.ci.openshift.org/openshift:console
Expand Down Expand Up @@ -98,3 +100,9 @@ spec:
secret:
secretName: serving-cert
optional: true
- name: trusted-ca
configMap:
name: trusted-ca
items:
- key: ca-bundle.crt
path: tls-ca-bundle.pem
45 changes: 29 additions & 16 deletions pkg/console/controllers/clidownloads/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
// standard lib
"context"
"fmt"
"net/url"
"time"

// kube
Expand Down Expand Up @@ -114,25 +115,37 @@ func (c *CLIDownloadsSyncController) Sync(ctx context.Context, controllerContext
}

statusHandler := status.NewStatusHandler(c.operatorClient)
ingressConfig, err := c.ingressConfigLister.Get(api.ConfigResourceName)
if err != nil {
return statusHandler.FlushAndReturn(err)
}

activeRouteName := api.OpenShiftConsoleDownloadsRouteName
routeConfig := routesub.NewRouteConfig(updatedOperatorConfig, ingressConfig, activeRouteName)
if routeConfig.IsCustomHostnameSet() {
activeRouteName = api.OpenshiftDownloadsCustomRouteName
}
var (
downloadsURI *url.URL
downloadsErr error
)
if len(operatorConfig.Spec.Ingress.ClientDownloadsURL) == 0 {
ingressConfig, err := c.ingressConfigLister.Get(api.ConfigResourceName)
if err != nil {
return statusHandler.FlushAndReturn(err)
}

downloadsRoute, downloadsRouteErr := c.routeLister.Routes(api.TargetNamespace).Get(activeRouteName)
if downloadsRouteErr != nil {
return downloadsRouteErr
}
activeRouteName := api.OpenShiftConsoleDownloadsRouteName
routeConfig := routesub.NewRouteConfig(updatedOperatorConfig, ingressConfig, activeRouteName)
if routeConfig.IsCustomHostnameSet() {
activeRouteName = api.OpenshiftDownloadsCustomRouteName
}

downloadsRoute, downloadsRouteErr := c.routeLister.Routes(api.TargetNamespace).Get(activeRouteName)
if downloadsRouteErr != nil {
return downloadsRouteErr
}

downloadsURI, _, downloadsRouteErr := routeapihelpers.IngressURI(downloadsRoute, downloadsRoute.Spec.Host)
if downloadsRouteErr != nil {
return downloadsRouteErr
downloadsURI, _, downloadsErr = routeapihelpers.IngressURI(downloadsRoute, downloadsRoute.Spec.Host)
if downloadsErr != nil {
return downloadsErr
}
} else {
downloadsURI, downloadsErr = url.Parse(operatorConfig.Spec.Ingress.ClientDownloadsURL)
if downloadsErr != nil {
return fmt.Errorf("failed to parse downloads url: %w", downloadsErr)
}
}

ocConsoleCLIDownloads := PlatformBasedOCConsoleCLIDownloads(downloadsURI.String(), api.OCCLIDownloadsCustomResourceName)
Expand Down
22 changes: 17 additions & 5 deletions pkg/console/controllers/healthcheck/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto/x509"
"fmt"
"net/http"
"net/url"
"time"

// k8s
Expand Down Expand Up @@ -78,7 +79,6 @@ func NewHealthCheckController(
util.IncludeNamesFilter(api.ConfigResourceName),
operatorConfigInformer.Informer(),
configV1Informers.Ingresses().Informer(),
configV1Informers.Infrastructures().Informer(),
).WithFilteredEventsInformers( // service
util.IncludeNamesFilter(api.TrustedCAConfigMapName, api.OAuthServingCertConfigMapName),
configMapInformer.Informer(),
Expand Down Expand Up @@ -153,10 +153,22 @@ func (c *HealthCheckController) CheckRouteHealth(ctx context.Context, operatorCo
retry.DefaultRetry,
func(err error) bool { return err != nil },
func() error {
url, _, err := routeapihelpers.IngressURI(route, route.Spec.Host)
if err != nil {
reason = "RouteNotAdmitted"
return fmt.Errorf("console route is not admitted")
var (
url *url.URL
err error
)
if len(operatorConfig.Spec.Ingress.ConsoleURL) == 0 {
url, _, err = routeapihelpers.IngressURI(route, route.Spec.Host)
if err != nil {
reason = "RouteNotAdmitted"
return fmt.Errorf("console route is not admitted")
}
} else {
url, err = url.Parse(operatorConfig.Spec.Ingress.ConsoleURL)
if err != nil {
reason = "FailedParseConsoleURL"
return fmt.Errorf("failed to parse console url: %w", err)
}
}

caPool, err := c.getCA(ctx, route.Spec.TLS)
Expand Down
Loading