Add OIDC client as a platform managed application
Add an OIDC client application to be deployed as a container for Kubernetes authentication. This application will be packaged into an RPM and automatically uploaded on controller-0 unlock. Story: 2006711 Task: 38166 Change-Id: I25c2b5ee7063d77722002df09afcc7d6725ebe8c Signed-off-by: Teresa Ho <teresa.ho@windriver.com>
This commit is contained in:
parent
883c333075
commit
a63597fc03
@ -1 +1,3 @@
|
||||
dex-helm
|
||||
stx-oidc-auth-helm
|
||||
stx-oidc-client
|
||||
|
1
centos_stable_docker_images.inc
Normal file
1
centos_stable_docker_images.inc
Normal file
@ -0,0 +1 @@
|
||||
stx-oidc-client
|
7
dex-helm/centos/build_srpm.data
Normal file
7
dex-helm/centos/build_srpm.data
Normal file
@ -0,0 +1,7 @@
|
||||
TAR_NAME=helm-charts
|
||||
SHA=92b6289ae93816717a8453cfe62bad51cbdb8ad0
|
||||
VERSION=1.0.0
|
||||
TAR="$TAR_NAME-$SHA.tar.gz"
|
||||
|
||||
COPY_LIST="${CGCS_BASE}/downloads/$TAR $PKG_BASE/files/* "
|
||||
TIS_PATCH_VER=0
|
77
dex-helm/centos/dex-helm.spec
Normal file
77
dex-helm/centos/dex-helm.spec
Normal file
@ -0,0 +1,77 @@
|
||||
# Application tunables (maps to metadata)
|
||||
%global app_name oidc-auth-apps
|
||||
%global helm_repo stx-platform
|
||||
|
||||
# Install location
|
||||
%global app_folder /usr/local/share/applications/helm
|
||||
|
||||
# Build variables
|
||||
%global helm_folder /usr/lib/helm
|
||||
|
||||
%global sha 92b6289ae93816717a8453cfe62bad51cbdb8ad0
|
||||
|
||||
Summary: StarlingX OIDC auth Helm charts
|
||||
Name: dex-helm
|
||||
Version: 1.0
|
||||
Release: %{tis_patch_ver}%{?_tis_dist}
|
||||
License: Apache-2.0
|
||||
Group: base
|
||||
Packager: Wind River <info@windriver.com>
|
||||
URL: unknown
|
||||
|
||||
Source0: helm-charts-%{sha}.tar.gz
|
||||
Source1: repositories.yaml
|
||||
Source2: index.yaml
|
||||
Source3: Makefile
|
||||
|
||||
Patch01: 0001-Update-Dex-chart-for-Kubernetes-API-1.16.patch
|
||||
Patch02: 0002-add-image-pull-secrets.patch
|
||||
|
||||
BuildArch: noarch
|
||||
|
||||
BuildRequires: helm
|
||||
|
||||
%description
|
||||
StarlingX OIDC auth Helm charts
|
||||
|
||||
%prep
|
||||
#%setup
|
||||
%setup -n helm-charts
|
||||
%patch01 -p1
|
||||
%patch02 -p1
|
||||
|
||||
%build
|
||||
# initialize helm
|
||||
# helm init --client-only does not work if there is no networking
|
||||
# The following commands do essentially the same as: helm init
|
||||
%define helm_home %{getenv:HOME}/.helm
|
||||
mkdir %{helm_home}
|
||||
mkdir %{helm_home}/repository
|
||||
mkdir %{helm_home}/repository/cache
|
||||
mkdir %{helm_home}/repository/local
|
||||
mkdir %{helm_home}/plugins
|
||||
mkdir %{helm_home}/starters
|
||||
mkdir %{helm_home}/cache
|
||||
mkdir %{helm_home}/cache/archive
|
||||
|
||||
# Stage a repository file that only has a local repo
|
||||
cp %{SOURCE1} %{helm_home}/repository/repositories.yaml
|
||||
|
||||
# Stage a local repo index that can be updated by the build
|
||||
cp %{SOURCE2} %{helm_home}/repository/local/index.yaml
|
||||
|
||||
# Make the charts. These produce a tgz file
|
||||
cp %{SOURCE3} stable
|
||||
which make
|
||||
cd stable
|
||||
make dex
|
||||
cd -
|
||||
|
||||
%install
|
||||
install -d -m 755 ${RPM_BUILD_ROOT}%{helm_folder}
|
||||
install -p -D -m 755 stable/*.tgz ${RPM_BUILD_ROOT}%{helm_folder}
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{helm_folder}/*
|
@ -1,7 +1,3 @@
|
||||
TAR_NAME=helm-charts
|
||||
SHA=92b6289ae93816717a8453cfe62bad51cbdb8ad0
|
||||
VERSION=1.0.0
|
||||
TAR="$TAR_NAME-$SHA.tar.gz"
|
||||
SRC_DIR="stx-oidc-auth-helm"
|
||||
|
||||
COPY_LIST="${CGCS_BASE}/downloads/helm-charts-92b6289ae93816717a8453cfe62bad51cbdb8ad0.tar.gz $PKG_BASE/files/* "
|
||||
TIS_PATCH_VER=0
|
||||
|
@ -8,8 +8,6 @@
|
||||
# Build variables
|
||||
%global helm_folder /usr/lib/helm
|
||||
|
||||
%global sha 92b6289ae93816717a8453cfe62bad51cbdb8ad0
|
||||
|
||||
Summary: StarlingX OIDC auth Helm charts
|
||||
Name: stx-oidc-auth-helm
|
||||
Version: 1.0
|
||||
@ -19,29 +17,19 @@ Group: base
|
||||
Packager: Wind River <info@windriver.com>
|
||||
URL: unknown
|
||||
|
||||
#Source0: %{name}-%{version}.tar.gz
|
||||
Source0: helm-charts-%{sha}.tar.gz
|
||||
Source1: repositories.yaml
|
||||
Source2: index.yaml
|
||||
Source3: metadata.yaml
|
||||
Source4: manifest.yaml
|
||||
Source5: Makefile
|
||||
|
||||
Patch01: 0001-Update-Dex-chart-for-Kubernetes-API-1.16.patch
|
||||
Patch02: 0002-add-image-pull-secrets.patch
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
|
||||
BuildArch: noarch
|
||||
|
||||
BuildRequires: helm
|
||||
BuildRequires: dex-helm
|
||||
Requires: dex-helm
|
||||
|
||||
%description
|
||||
StarlingX OIDC auth Helm charts
|
||||
|
||||
%prep
|
||||
#%setup
|
||||
%setup -n helm-charts
|
||||
%patch01 -p1
|
||||
%patch02 -p1
|
||||
%setup
|
||||
|
||||
%build
|
||||
# initialize helm
|
||||
@ -58,10 +46,10 @@ mkdir %{helm_home}/cache
|
||||
mkdir %{helm_home}/cache/archive
|
||||
|
||||
# Stage a repository file that only has a local repo
|
||||
cp %{SOURCE1} %{helm_home}/repository/repositories.yaml
|
||||
cp files/repositories.yaml %{helm_home}/repository/repositories.yaml
|
||||
|
||||
# Stage a local repo index that can be updated by the build
|
||||
cp %{SOURCE2} %{helm_home}/repository/local/index.yaml
|
||||
cp files/index.yaml %{helm_home}/repository/local/index.yaml
|
||||
|
||||
# Host a server for the charts
|
||||
helm serve --repo-path . &
|
||||
@ -69,9 +57,8 @@ helm repo rm local
|
||||
helm repo add local http://localhost:8879/charts
|
||||
|
||||
# Make the charts. These produce a tgz file
|
||||
cp %{SOURCE5} stable
|
||||
cd stable
|
||||
make dex
|
||||
cd helm-charts
|
||||
make oidc-client
|
||||
cd -
|
||||
|
||||
# Terminate helm server (the last backgrounded task)
|
||||
@ -83,10 +70,11 @@ kill %1
|
||||
|
||||
# Setup staging
|
||||
mkdir -p %{app_staging}
|
||||
cp %{SOURCE3} %{app_staging}
|
||||
cp %{SOURCE4} %{app_staging}
|
||||
cp files/metadata.yaml %{app_staging}
|
||||
cp manifests/manifest.yaml %{app_staging}
|
||||
mkdir -p %{app_staging}/charts
|
||||
cp stable/*.tgz %{app_staging}/charts
|
||||
cp helm-charts/*.tgz %{app_staging}/charts
|
||||
cp %{helm_folder}/dex*.tgz %{app_staging}/charts
|
||||
cd %{app_staging}
|
||||
|
||||
# Populate metadata
|
||||
|
3
stx-oidc-auth-helm/stx-oidc-auth-helm/files/index.yaml
Normal file
3
stx-oidc-auth-helm/stx-oidc-auth-helm/files/index.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
apiVersion: v1
|
||||
entries: {}
|
||||
generated: 2019-01-07T12:33:46.098166523-06:00
|
@ -0,0 +1,3 @@
|
||||
app_name: @APP_NAME@
|
||||
app_version: @APP_VERSION@
|
||||
helm_repo: @HELM_REPO@
|
@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
generated: 2019-01-02T15:19:36.215111369-06:00
|
||||
repositories:
|
||||
- caFile: ""
|
||||
cache: /builddir/.helm/repository/cache/local-index.yaml
|
||||
certFile: ""
|
||||
keyFile: ""
|
||||
name: local
|
||||
password: ""
|
||||
url: http://127.0.0.1:8879/charts
|
||||
username: ""
|
||||
|
43
stx-oidc-auth-helm/stx-oidc-auth-helm/helm-charts/Makefile
Normal file
43
stx-oidc-auth-helm/stx-oidc-auth-helm/helm-charts/Makefile
Normal file
@ -0,0 +1,43 @@
|
||||
#
|
||||
# Copyright 2017 The Openstack-Helm Authors.
|
||||
#
|
||||
# Copyright (c) 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# It's necessary to set this because some environments don't link sh -> bash.
|
||||
SHELL := /bin/bash
|
||||
TASK := build
|
||||
|
||||
EXCLUDES := helm-toolkit doc tests tools logs tmp
|
||||
CHARTS := helm-toolkit $(filter-out $(EXCLUDES), $(patsubst %/.,%,$(wildcard */.)))
|
||||
|
||||
.PHONY: $(EXCLUDES) $(CHARTS)
|
||||
|
||||
all: $(CHARTS)
|
||||
|
||||
$(CHARTS):
|
||||
@if [ -d $@ ]; then \
|
||||
echo; \
|
||||
echo "===== Processing [$@] chart ====="; \
|
||||
make $(TASK)-$@; \
|
||||
fi
|
||||
|
||||
init-%:
|
||||
if [ -f $*/Makefile ]; then make -C $*; fi
|
||||
if [ -f $*/requirements.yaml ]; then helm dep up $*; fi
|
||||
|
||||
lint-%: init-%
|
||||
if [ -d $* ]; then helm lint $*; fi
|
||||
|
||||
build-%: lint-%
|
||||
if [ -d $* ]; then helm package $*; fi
|
||||
|
||||
clean:
|
||||
@echo "Clean all build artifacts"
|
||||
rm -f */templates/_partials.tpl */templates/_globals.tpl
|
||||
rm -f *tgz */charts/*tgz */requirements.lock
|
||||
rm -rf */charts */tmpcharts
|
||||
|
||||
%:
|
||||
@:
|
@ -0,0 +1,5 @@
|
||||
apiVersion: v1
|
||||
appVersion: "1.0"
|
||||
description: A Helm chart for Kubernetes
|
||||
name: oidc-client
|
||||
version: 0.1.0
|
@ -0,0 +1,32 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "stx-oidc-client.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "stx-oidc-client.fullname" -}}
|
||||
{{- if .Values.fullnameOverride -}}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- if contains $name .Release.Name -}}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "stx-oidc-client.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
@ -0,0 +1,19 @@
|
||||
{{/*
|
||||
#
|
||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
*/}}
|
||||
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: stx-oidc-client
|
||||
labels:
|
||||
app: stx-oidc-client
|
||||
data:
|
||||
config.yaml: |-
|
||||
{{- with .Values.config }}
|
||||
{{ toYaml . | indent 4 }}
|
||||
{{- end }}
|
@ -0,0 +1,70 @@
|
||||
{{/*
|
||||
#
|
||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
*/}}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: stx-oidc-client
|
||||
labels:
|
||||
app: stx-oidc-client
|
||||
spec:
|
||||
replicas: {{ .Values.replicas }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: stx-oidc-client
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: stx-oidc-client
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: default-registry-key
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
command: ["./stx-oidc-client"]
|
||||
args: ["--config", "config.yaml", "--debug"]
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 5555
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
volumeMounts:
|
||||
- mountPath: "/home"
|
||||
name: dex-client-secret-volume
|
||||
- name: config
|
||||
subPath: config.yaml
|
||||
mountPath: /app/config.yaml
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: dex-client-secret-volume
|
||||
secret:
|
||||
secretName: dex-client-secret
|
||||
- name: config
|
||||
configMap:
|
||||
name: stx-oidc-client
|
@ -0,0 +1,46 @@
|
||||
{{/*
|
||||
#
|
||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
*/}}
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "stx-oidc-client.fullname" . -}}
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "stx-oidc-client.name" . }}
|
||||
helm.sh/chart: {{ include "stx-oidc-client.chart" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ . }}
|
||||
backend:
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: http
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
@ -0,0 +1,23 @@
|
||||
{{/*
|
||||
#
|
||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
*/}}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: stx-oidc-client
|
||||
labels:
|
||||
app: stx-oidc-client
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: 5555
|
||||
protocol: TCP
|
||||
name: http
|
||||
nodePort: {{ .Values.service.nodePort }}
|
||||
selector:
|
||||
app: stx-oidc-client
|
@ -0,0 +1,48 @@
|
||||
#
|
||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# Default values for stx-oidc-client.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicas: 1
|
||||
|
||||
image:
|
||||
repository: docker.io/starlingx/stx-oidc-client
|
||||
tag: v1.0.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
service:
|
||||
type: NodePort
|
||||
port: 5555
|
||||
nodePort: 30555
|
||||
|
||||
config:
|
||||
client_id: stx-oidc-client-app
|
||||
client_secret: St8rlingX
|
||||
issuer: https://10.10.10.3:30556/dex
|
||||
issuer_root_ca: /home/dex-ca.pem
|
||||
listen: http://0.0.0.0:5555
|
||||
redirect_uri: http://10.10.10.3:30555/callback
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
hosts:
|
||||
- host: chart-example.local
|
||||
paths: []
|
||||
tls: []
|
||||
|
||||
resources: {}
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
@ -50,6 +50,43 @@ data:
|
||||
reference: master
|
||||
dependencies: []
|
||||
---
|
||||
schema: armada/Chart/v1
|
||||
metadata:
|
||||
schema: metadata/Document/v1
|
||||
name: kube-system-oidc-client
|
||||
data:
|
||||
chart_name: oidc-client
|
||||
release: oidc-client
|
||||
namespace: kube-system
|
||||
wait:
|
||||
timeout: 1800
|
||||
labels:
|
||||
app: dex
|
||||
install:
|
||||
no_hooks: false
|
||||
upgrade:
|
||||
no_hooks: false
|
||||
pre:
|
||||
delete:
|
||||
- type: job
|
||||
labels:
|
||||
app: oidc-client
|
||||
values:
|
||||
config:
|
||||
issuer_root_ca: /home/dex-ca.pem
|
||||
listen: http://0.0.0.0:5555
|
||||
nodeSelector:
|
||||
node-role.kubernetes.io/master: ""
|
||||
service:
|
||||
type: NodePort
|
||||
port: 5555
|
||||
source:
|
||||
type: tar
|
||||
location: http://172.17.0.1:8080/helm_charts/stx-platform/oidc-client-0.1.0.tgz
|
||||
subpath: oidc-client
|
||||
reference: master
|
||||
dependencies: []
|
||||
---
|
||||
schema: armada/ChartGroup/v1
|
||||
metadata:
|
||||
schema: metadata/Document/v1
|
||||
@ -59,6 +96,7 @@ data:
|
||||
sequenced: true
|
||||
chart_group:
|
||||
- kube-system-dex
|
||||
- kube-system-oidc-client
|
||||
---
|
||||
schema: armada/Manifest/v1
|
||||
metadata:
|
2
stx-oidc-client/centos/build_srpm.data
Normal file
2
stx-oidc-client/centos/build_srpm.data
Normal file
@ -0,0 +1,2 @@
|
||||
SRC_DIR="stx-oidc-client"
|
||||
TIS_PATCH_VER=1
|
8
stx-oidc-client/centos/docker/Dockerfile
Normal file
8
stx-oidc-client/centos/docker/Dockerfile
Normal file
@ -0,0 +1,8 @@
|
||||
FROM golang:latest
|
||||
WORKDIR /app
|
||||
ADD . /app/
|
||||
RUN go get -d -v ./...
|
||||
RUN go build -o stx-oidc-client .
|
||||
|
||||
EXPOSE 5555
|
||||
CMD ["./stx-oidc-client"]
|
261
stx-oidc-client/centos/docker/Gopkg.lock
generated
Normal file
261
stx-oidc-client/centos/docker/Gopkg.lock
generated
Normal file
@ -0,0 +1,261 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
digest = "1:d64c893fc7d2c3d395f421b00d21f0adb8ceffc4d3c90299e732b3985ca16eb4"
|
||||
name = "github.com/coreos/go-oidc"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "2be1c5b8a260760503f66dc0996e102b683b3ac3"
|
||||
version = "v2.1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd"
|
||||
name = "github.com/fsnotify/fsnotify"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
|
||||
version = "v1.4.7"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:573ca21d3669500ff845bdebee890eb7fc7f0f50c59f2132f2a0c6b03d85086a"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = ["proto"]
|
||||
pruneopts = "UT"
|
||||
revision = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7"
|
||||
version = "v1.3.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10"
|
||||
name = "github.com/hashicorp/hcl"
|
||||
packages = [
|
||||
".",
|
||||
"hcl/ast",
|
||||
"hcl/parser",
|
||||
"hcl/printer",
|
||||
"hcl/scanner",
|
||||
"hcl/strconv",
|
||||
"hcl/token",
|
||||
"json/parser",
|
||||
"json/scanner",
|
||||
"json/token",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "8cb6e5b959231cc1119e43259c4a608f9c51a241"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
|
||||
name = "github.com/inconshreveable/mousetrap"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:5a0ef768465592efca0412f7e838cdc0826712f8447e70e6ccc52eb441e9ab13"
|
||||
name = "github.com/magiconair/properties"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "de8848e004dd33dc07a2947b3d76f618a7fc7ef1"
|
||||
version = "v1.8.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:53bc4cd4914cd7cd52139990d5170d6dc99067ae31c56530621b18b35fc30318"
|
||||
name = "github.com/mitchellh/mapstructure"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "3536a929edddb9a5b34bd6861dc4a9647cb459fe"
|
||||
version = "v1.1.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:6eea828983c70075ca297bb915ffbcfd3e34c5a50affd94428a65df955c0ff9c"
|
||||
name = "github.com/pelletier/go-toml"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "903d9455db9ff1d7ac1ab199062eca7266dd11a3"
|
||||
version = "v1.6.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:bd9efe4e0b0f768302a1e2f0c22458149278de533e521206e5ddc71848c269a0"
|
||||
name = "github.com/pquerna/cachecontrol"
|
||||
packages = [
|
||||
".",
|
||||
"cacheobject",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "1555304b9b35fdd2b425bccf1a5613677705e7d0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:bb495ec276ab82d3dd08504bbc0594a65de8c3b22c6f2aaa92d05b73fbf3a82e"
|
||||
name = "github.com/spf13/afero"
|
||||
packages = [
|
||||
".",
|
||||
"mem",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "588a75ec4f32903aa5e39a2619ba6a4631e28424"
|
||||
version = "v1.2.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:08d65904057412fc0270fc4812a1c90c594186819243160dc779a402d4b6d0bc"
|
||||
name = "github.com/spf13/cast"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "8c9545af88b134710ab1cd196795e7f2388358d7"
|
||||
version = "v1.3.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:e096613fb7cf34743d49af87d197663cfccd61876e2219853005a57baedfa562"
|
||||
name = "github.com/spf13/cobra"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "f2b07da1e2c38d5f12845a4f607e2e1018cbb1f5"
|
||||
version = "v0.0.5"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:1b753ec16506f5864d26a28b43703c58831255059644351bbcb019b843950900"
|
||||
name = "github.com/spf13/jwalterweatherman"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "94f6ae3ed3bceceafa716478c5fbf8d29ca601a1"
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:524b71991fc7d9246cc7dc2d9e0886ccb97648091c63e30eef619e6862c955dd"
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "2e9d26c8c37aae03e3f9d4e90b7116f5accb7cab"
|
||||
version = "v1.0.5"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8d0b79a29be9946ea00b2f2b778ec5b36db07453d97abe9d754b25bc2cc49a0e"
|
||||
name = "github.com/spf13/viper"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "eabbc68a3ecd5cf8c11a2f84dbda5e7a38493b2f"
|
||||
version = "v1.6.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:f4b32291cad5efac2bfdba89ccde6aa04618b62ce06c1a571da2dc4f3f2677fb"
|
||||
name = "github.com/subosito/gotenv"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "2ef7124db659d49edac6aa459693a15ae36c671a"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:5cdf4eb6946922ebe638b90e548e1a86085b778d9daf0889951b39f44e6bbe6c"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = [
|
||||
"ed25519",
|
||||
"ed25519/internal/edwards25519",
|
||||
"pbkdf2",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "4f8c1d86b1ba699e7a66cd649947ed270a74e0bb"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:f8b491a7c25030a895a0e579742d07136e6958e77ef2d46e769db8eec4e58fcd"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
"context/ctxhttp",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "fc4aabc6c91483155dade6fbb627cc953a723260"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:8d1c112fb1679fa097e9a9255a786ee47383fa2549a3da71bcb1334a693ebcfe"
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [
|
||||
".",
|
||||
"internal",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "0f29369cfe4552d0e4bcddc57cc75f4d7e672a33"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:634414cd43ed62a728aaf9b3e61fde85f012880f9b32b7d00678b6fd887ff9c1"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
pruneopts = "UT"
|
||||
revision = "ac6580df4449443a05718fd7858c1f91ad5f8d20"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:1093f2eb4b344996604f7d8b29a16c5b22ab9e1b25652140d3fede39f640d5cd"
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"internal/gen",
|
||||
"internal/triegen",
|
||||
"internal/ucd",
|
||||
"transform",
|
||||
"unicode/cldr",
|
||||
"unicode/norm",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "342b2e1fbaa52c93f31447ad2c6abc048c63e475"
|
||||
version = "v0.3.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:e0a1881f9e0564bebdeac98c75e59f07acdde6ed3a5396e0e613eaad31194866"
|
||||
name = "google.golang.org/appengine"
|
||||
packages = [
|
||||
"internal",
|
||||
"internal/base",
|
||||
"internal/datastore",
|
||||
"internal/log",
|
||||
"internal/remote_api",
|
||||
"internal/urlfetch",
|
||||
"urlfetch",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "971852bfffca25b069c31162ae8f247a3dba083b"
|
||||
version = "v1.6.5"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:591460fbfc463bda7071ac906bed19cbf64cffd5fcb80a6d1490e87b9dfad942"
|
||||
name = "gopkg.in/ini.v1"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "87e589f4917038ae250cff2446db7573f47e97ca"
|
||||
version = "v1.51.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:8ebd7bc4892e673e8d3c6377c71e8c691b92c5e51cd3159efb8343b580213b70"
|
||||
name = "gopkg.in/square/go-jose.v2"
|
||||
packages = [
|
||||
".",
|
||||
"cipher",
|
||||
"json",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "8fd82ff1d52a5162ff23c0a48e2c64a1fa4a3f8f"
|
||||
version = "v2.4.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:b75b3deb2bce8bc079e16bb2aecfe01eb80098f5650f9e93e5643ca8b7b73737"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "1f64d6156d11335c3f22d9330b0ad14fc1e789ce"
|
||||
version = "v2.2.7"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/coreos/go-oidc",
|
||||
"github.com/spf13/cobra",
|
||||
"github.com/spf13/pflag",
|
||||
"github.com/spf13/viper",
|
||||
"golang.org/x/oauth2",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
42
stx-oidc-client/centos/docker/Gopkg.toml
Normal file
42
stx-oidc-client/centos/docker/Gopkg.toml
Normal file
@ -0,0 +1,42 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/coreos/go-oidc"
|
||||
version = "2.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/spf13/cobra"
|
||||
version = "0.0.5"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
371
stx-oidc-client/centos/docker/main.go
Normal file
371
stx-oidc-client/centos/docker/main.go
Normal file
@ -0,0 +1,371 @@
|
||||
// Initial file was taken from https://github.com/dexidp/dex/tree/master/cmd/example-app 2019
|
||||
//
|
||||
// Copyright (c) 2020 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const exampleAppState = "I wish to wash my irish wristwatch"
|
||||
|
||||
var (
|
||||
config_file string
|
||||
debug bool
|
||||
)
|
||||
|
||||
type app struct {
|
||||
clientID string
|
||||
clientSecret string
|
||||
redirectURI string
|
||||
|
||||
verifier *oidc.IDTokenVerifier
|
||||
provider *oidc.Provider
|
||||
|
||||
// Does the provider use "offline_access" scope to request a refresh token
|
||||
// or does it use "access_type=offline" (e.g. Google)?
|
||||
offlineAsScope bool
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
a app
|
||||
issuerURL string
|
||||
listen string
|
||||
tlsCert string
|
||||
tlsKey string
|
||||
rootCAs string
|
||||
debug bool
|
||||
}
|
||||
|
||||
// return an HTTP client which trusts the provided root CAs.
|
||||
func httpClientForRootCAs(rootCAs string) (*http.Client, error) {
|
||||
tlsConfig := tls.Config{RootCAs: x509.NewCertPool()}
|
||||
rootCABytes, err := ioutil.ReadFile(rootCAs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read root-ca: %v", err)
|
||||
}
|
||||
if !tlsConfig.RootCAs.AppendCertsFromPEM(rootCABytes) {
|
||||
return nil, fmt.Errorf("no certs found in root CA file %q", rootCAs)
|
||||
}
|
||||
return &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tlsConfig,
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
type debugTransport struct {
|
||||
t http.RoundTripper
|
||||
}
|
||||
|
||||
func (d debugTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
reqDump, err := httputil.DumpRequest(req, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("%s", reqDump)
|
||||
|
||||
resp, err := d.t.RoundTrip(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respDump, err := httputil.DumpResponse(resp, true)
|
||||
if err != nil {
|
||||
resp.Body.Close()
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("%s", respDump)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func start_app(config Config) {
|
||||
u, err := url.Parse(config.a.redirectURI)
|
||||
if err != nil {
|
||||
log.Fatalf("parse redirect-uri: %v", err)
|
||||
}
|
||||
listenURL, err := url.Parse(config.listen)
|
||||
if err != nil {
|
||||
log.Fatalf("parse listen address: %v", err)
|
||||
}
|
||||
|
||||
if config.rootCAs != "" {
|
||||
client, err := httpClientForRootCAs(config.rootCAs)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse a trusted cert: %v", err)
|
||||
}
|
||||
config.a.client = client
|
||||
}
|
||||
|
||||
if debug {
|
||||
if config.a.client == nil {
|
||||
config.a.client = &http.Client{
|
||||
Transport: debugTransport{http.DefaultTransport},
|
||||
}
|
||||
} else {
|
||||
config.a.client.Transport = debugTransport{config.a.client.Transport}
|
||||
}
|
||||
}
|
||||
|
||||
if config.a.client == nil {
|
||||
config.a.client = http.DefaultClient
|
||||
}
|
||||
|
||||
ctx := oidc.ClientContext(context.Background(), config.a.client)
|
||||
provider, err := oidc.NewProvider(ctx, config.issuerURL)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to query provider %q: %v", config.issuerURL, err)
|
||||
}
|
||||
|
||||
var s struct {
|
||||
ScopesSupported []string `json:"scopes_supported"`
|
||||
}
|
||||
if err := provider.Claims(&s); err != nil {
|
||||
log.Fatalf("Failed to parse provider scopes_supported: %v", err)
|
||||
}
|
||||
|
||||
if len(s.ScopesSupported) == 0 {
|
||||
// scopes_supported is a "RECOMMENDED" discovery claim, not a required
|
||||
// one. If missing, assume that the provider follows the spec and has
|
||||
// an "offline_access" scope.
|
||||
config.a.offlineAsScope = true
|
||||
} else {
|
||||
// See if scopes_supported has the "offline_access" scope.
|
||||
config.a.offlineAsScope = func() bool {
|
||||
for _, scope := range s.ScopesSupported {
|
||||
if scope == oidc.ScopeOfflineAccess {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}()
|
||||
}
|
||||
|
||||
config.a.provider = provider
|
||||
config.a.verifier = provider.Verifier(&oidc.Config{ClientID: config.a.clientID})
|
||||
|
||||
http.HandleFunc("/", config.a.handleLogin)
|
||||
http.HandleFunc(u.Path, config.a.handleCallback)
|
||||
|
||||
switch listenURL.Scheme {
|
||||
case "http":
|
||||
log.Printf("listening on %s", config.listen)
|
||||
http.ListenAndServe(listenURL.Host, nil)
|
||||
case "https":
|
||||
log.Printf("listening on %s", config.listen)
|
||||
http.ListenAndServeTLS(listenURL.Host, config.tlsCert, config.tlsKey, nil)
|
||||
default:
|
||||
fmt.Errorf("listen address %q is not using http or https", config.listen)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "oidc-client",
|
||||
Short: "Dex Kubernetes Client",
|
||||
Long: "",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
var config Config
|
||||
err := viper.Unmarshal(&config)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to decode configuration into struct, %v", err)
|
||||
}
|
||||
|
||||
config.issuerURL = viper.GetString("issuer")
|
||||
config.listen = viper.GetString("listen")
|
||||
config.rootCAs = viper.GetString("issuer_root_ca")
|
||||
config.a.clientID = viper.GetString("client_id")
|
||||
config.a.clientSecret = viper.GetString("client_secret")
|
||||
config.a.redirectURI = viper.GetString("redirect_uri")
|
||||
log.Printf("config=%+v", config)
|
||||
|
||||
// Start the app
|
||||
start_app(config)
|
||||
},
|
||||
}
|
||||
|
||||
// Read in config file
|
||||
func initConfig() {
|
||||
if config_file != "" {
|
||||
viper.SetConfigFile(config_file)
|
||||
viper.SetConfigType("yaml")
|
||||
|
||||
// If a config file is found, read it in.
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
log.Printf("Fatal error config file: %s \n", err)
|
||||
} else {
|
||||
log.Printf("using config file: %s", viper.ConfigFileUsed())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialization
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
viper.BindPFlags(rootCmd.Flags())
|
||||
rootCmd.Flags().StringVar(&config_file, "config", "", "./config.yaml")
|
||||
rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "Enable debug logging")
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *app) oauth2Config(scopes []string) *oauth2.Config {
|
||||
return &oauth2.Config{
|
||||
ClientID: a.clientID,
|
||||
ClientSecret: a.clientSecret,
|
||||
Endpoint: a.provider.Endpoint(),
|
||||
Scopes: scopes,
|
||||
RedirectURL: a.redirectURI,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *app) handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||
var scopes []string
|
||||
if extraScopes := r.FormValue("extra_scopes"); extraScopes != "" {
|
||||
scopes = strings.Split(extraScopes, " ")
|
||||
}
|
||||
var clients []string
|
||||
if crossClients := r.FormValue("cross_client"); crossClients != "" {
|
||||
clients = strings.Split(crossClients, " ")
|
||||
}
|
||||
for _, client := range clients {
|
||||
scopes = append(scopes, "audience:server:client_id:"+client)
|
||||
}
|
||||
connectorID := ""
|
||||
if id := r.FormValue("connector_id"); id != "" {
|
||||
connectorID = id
|
||||
}
|
||||
|
||||
authCodeURL := ""
|
||||
scopes = append(scopes, "openid", "profile", "email")
|
||||
if r.FormValue("offline_access") != "yes" {
|
||||
authCodeURL = a.oauth2Config(scopes).AuthCodeURL(exampleAppState)
|
||||
} else if a.offlineAsScope {
|
||||
scopes = append(scopes, "offline_access")
|
||||
authCodeURL = a.oauth2Config(scopes).AuthCodeURL(exampleAppState)
|
||||
} else {
|
||||
authCodeURL = a.oauth2Config(scopes).AuthCodeURL(exampleAppState, oauth2.AccessTypeOffline)
|
||||
}
|
||||
if connectorID != "" {
|
||||
authCodeURL = authCodeURL + "&connector_id=" + connectorID
|
||||
}
|
||||
http.Redirect(w, r, authCodeURL, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (a *app) handleCallback(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
err error
|
||||
token *oauth2.Token
|
||||
)
|
||||
log.Printf("In handleCallback")
|
||||
ctx := oidc.ClientContext(r.Context(), a.client)
|
||||
oauth2Config := a.oauth2Config(nil)
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
// Authorization redirect callback from OAuth2 auth flow.
|
||||
if errMsg := r.FormValue("error"); errMsg != "" {
|
||||
http.Error(w, errMsg+": "+r.FormValue("error_description"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
code := r.FormValue("code")
|
||||
if code == "" {
|
||||
http.Error(w, fmt.Sprintf("no code in request: %q", r.Form), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if state := r.FormValue("state"); state != exampleAppState {
|
||||
http.Error(w, fmt.Sprintf("expected state %q got %q", exampleAppState, state), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
token, err = oauth2Config.Exchange(ctx, code)
|
||||
case http.MethodPost:
|
||||
// Form request from frontend to refresh a token.
|
||||
refresh := r.FormValue("refresh_token")
|
||||
if refresh == "" {
|
||||
http.Error(w, fmt.Sprintf("no refresh_token in request: %q", r.Form), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
t := &oauth2.Token{
|
||||
RefreshToken: refresh,
|
||||
Expiry: time.Now().Add(-time.Hour),
|
||||
}
|
||||
token, err = oauth2Config.TokenSource(ctx, t).Token()
|
||||
default:
|
||||
http.Error(w, fmt.Sprintf("method not implemented: %s", r.Method), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get token: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
rawIDToken, ok := token.Extra("id_token").(string)
|
||||
if !ok {
|
||||
http.Error(w, "no id_token in token response", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
idToken, err := a.verifier.Verify(r.Context(), rawIDToken)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to verify ID token: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
accessToken, ok := token.Extra("access_token").(string)
|
||||
if !ok {
|
||||
http.Error(w, "no access_token in token response", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var claims json.RawMessage
|
||||
if err := idToken.Claims(&claims); err != nil {
|
||||
http.Error(w, fmt.Sprintf("error decoding ID token claims: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
buff := new(bytes.Buffer)
|
||||
if err := json.Indent(buff, []byte(claims), "", " "); err != nil {
|
||||
http.Error(w, fmt.Sprintf("error indenting ID token claims: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
renderToken(w, a.redirectURI, rawIDToken, accessToken, token.RefreshToken, buff.String())
|
||||
}
|
78
stx-oidc-client/centos/docker/template.go
Normal file
78
stx-oidc-client/centos/docker/template.go
Normal file
@ -0,0 +1,78 @@
|
||||
// Initial file was taken from https://github.com/dexidp/dex/tree/master/cmd/example-app 2019
|
||||
//
|
||||
// Copyright (c) 2020 Wind River Systems, Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type tokenTmplData struct {
|
||||
IDToken string
|
||||
AccessToken string
|
||||
RefreshToken string
|
||||
RedirectURL string
|
||||
Claims string
|
||||
}
|
||||
|
||||
var tokenTmpl = template.Must(template.New("token.html").Parse(`<html>
|
||||
<head>
|
||||
<style>
|
||||
/* make pre wrap */
|
||||
pre {
|
||||
white-space: pre-wrap; /* css-3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p> ID Token: <pre><code>{{ .IDToken }}</code></pre></p>
|
||||
<p> Access Token: <pre><code>{{ .AccessToken }}</code></pre></p>
|
||||
<p> Claims: <pre><code>{{ .Claims }}</code></pre></p>
|
||||
{{ if .RefreshToken }}
|
||||
<p> Refresh Token: <pre><code>{{ .RefreshToken }}</code></pre></p>
|
||||
<form action="{{ .RedirectURL }}" method="post">
|
||||
<input type="hidden" name="refresh_token" value="{{ .RefreshToken }}">
|
||||
<input type="submit" value="Redeem refresh token">
|
||||
</form>
|
||||
{{ end }}
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
|
||||
func renderToken(w http.ResponseWriter, redirectURL, idToken, accessToken, refreshToken, claims string) {
|
||||
renderTemplate(w, tokenTmpl, tokenTmplData{
|
||||
IDToken: idToken,
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
RedirectURL: redirectURL,
|
||||
Claims: claims,
|
||||
})
|
||||
}
|
||||
|
||||
func renderTemplate(w http.ResponseWriter, tmpl *template.Template, data interface{}) {
|
||||
err := tmpl.Execute(w, data)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch err := err.(type) {
|
||||
case *template.Error:
|
||||
// An ExecError guarantees that Execute has not written to the underlying reader.
|
||||
log.Printf("Error rendering template %s: %s", tmpl.Name(), err)
|
||||
|
||||
// TODO(ericchiang): replace with better internal server error.
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
default:
|
||||
// An error with the underlying write, such as the connection being
|
||||
// dropped. Ignore for now.
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
BUILDER=docker
|
||||
LABEL=stx-oidc-client
|
Loading…
x
Reference in New Issue
Block a user