Compare commits
30 Commits
main
...
ben/carvel
Author | SHA1 | Date | |
---|---|---|---|
|
a416faa100 | ||
|
d1e2e497eb | ||
|
621ef9b116 | ||
|
33adca878c | ||
|
c13f19ebc6 | ||
|
8fd267a162 | ||
|
e6dd0ff443 | ||
|
c6e4f4fd51 | ||
|
d306c9f20a | ||
|
20f41f0a32 | ||
|
3e0bdf1638 | ||
|
7b858d62a3 | ||
|
397d560693 | ||
|
2e7574c991 | ||
|
217429b840 | ||
|
e38e126045 | ||
|
bd0e197942 | ||
|
7d7597e2a8 | ||
|
55a8141e08 | ||
|
f8d173d6b3 | ||
|
c943a3602d | ||
|
167b1a58d0 | ||
|
4210810c71 | ||
|
6c0dccdfbd | ||
|
b3b7b77ae7 | ||
|
b4a3e5a1e3 | ||
|
a1c3766fca | ||
|
5d1320dd2a | ||
|
e7824bf714 | ||
|
7002e4dd13 |
318
deploy_carvel/build.sh
Executable file
318
deploy_carvel/build.sh
Executable file
@ -0,0 +1,318 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425
|
||||
set -e # immediately exit
|
||||
set -u # error if variables undefined
|
||||
set -o pipefail # prevent masking errors in a pipeline
|
||||
# set -x # print all executed commands to terminal
|
||||
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
DEFAULT='\033[0m'
|
||||
|
||||
echo_yellow() {
|
||||
echo -e "${YELLOW}>> $@${DEFAULT}\n"
|
||||
# printf "${GREEN}$@${DEFAULT}"
|
||||
}
|
||||
|
||||
echo_green() {
|
||||
echo -e "${GREEN}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
echo_red() {
|
||||
echo -e "${RED}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
echo_blue() {
|
||||
echo -e "${BLUE}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
|
||||
# got a cluster?
|
||||
echo_yellow "Verify you have a functional kind cluster, otherwise this will fail....."
|
||||
# ./kind-with-registry.sh
|
||||
# got kapp-controller bits?
|
||||
kubectl get customresourcedefinitions
|
||||
kapp deploy --app kapp-controller --file https://github.com/vmware-tanzu/carvel-kapp-controller/releases/latest/download/release.yml -y
|
||||
kubectl get customresourcedefinitions
|
||||
|
||||
# this argument is given to kapp-controller by default
|
||||
# in the above deployment manfiest:
|
||||
# -packaging-global-namespace=kapp-controller-packaging-global
|
||||
# which means, PackageRepos and Packages ought be installed in this
|
||||
# namespace to be globally available by default, since
|
||||
# PackageRepos and Packages are namespaced resources.
|
||||
KAPP_CONTROLLER_GLOBAL_NAMESPACE="kapp-controller-packaging-global"
|
||||
|
||||
# TODO: since I removed the deployments there is not much in the ./imgpkg/images.yaml output
|
||||
#
|
||||
# build images found in these directories.
|
||||
# make use of build.yaml files to specify how builds should work,
|
||||
# if we need it to be done.
|
||||
# kbld --file ./concierge/config --imgpkg-lock-output ./concierge/.imgpkg/images.yml
|
||||
|
||||
# this is used in the package-template.yml file for declaring where the package will live.
|
||||
# we need to know where these package images should live :)
|
||||
# REPO_HOST="1.2.3.4.fake.repo.host:5000"
|
||||
# PACKAGE_REPO_HOST="projects.registry.vmware.com/pinniped/pinniped-server"
|
||||
# PACKAGE_REPO_HOST="docker.io/benjaminapetersen/pinniped-package-repo"
|
||||
# PACKAGE_REPO_HOST="benjaminapetersen/pinniped-package-repo"
|
||||
PACKGE_REPO_HOST="localhost:5001/pinniped-package-repo"
|
||||
PINNIPED_PACKAGE_VERSION="0.25.0"
|
||||
|
||||
# TODO: cp ./deploy/supervisor.... into ./deploy_carvel/supervisor/config...
|
||||
# TODO: cp ./deploy/concierge.... into ./deploy_carvel/concierge/config...
|
||||
# -- we should copy this over, yeah?
|
||||
# NOTE: I did make changes to values.yaml to turn it into a values schema....
|
||||
|
||||
echo ""
|
||||
echo_yellow "cleaning ./package-repository..."
|
||||
PACKAGE_REPOSITORY_DIR="package-repository"
|
||||
rm -rf "./${PACKAGE_REPOSITORY_DIR}"
|
||||
mkdir -p "./${PACKAGE_REPOSITORY_DIR}/.imgpkg"
|
||||
mkdir -p "./${PACKAGE_REPOSITORY_DIR}/packages/concierge.pinniped.dev"
|
||||
mkdir -p "./${PACKAGE_REPOSITORY_DIR}/packages/supervisor.pinniped.dev"
|
||||
|
||||
PACKAGE_INSTALL_DIR="temp_actual_deploy_resources"
|
||||
rm -rf "./${PACKAGE_INSTALL_DIR}"
|
||||
mkdir "./${PACKAGE_INSTALL_DIR}"
|
||||
|
||||
## TODO:
|
||||
## "${resource_name}/deployment.yml" vs "${resource_name}/deployment-HACKED.yml"
|
||||
## the real one has images.
|
||||
## - CURRENTLY the deployment.yaml files don't work, there is some error with pushing images.
|
||||
## come back to this later?
|
||||
declare -a arr=("supervisor" "concierge")
|
||||
for resource_name in "${arr[@]}"
|
||||
do
|
||||
echo ""
|
||||
echo_yellow "handling ${resource_name}..."
|
||||
|
||||
# just simple templating
|
||||
echo_yellow "generating ${resource_name}/.imgpkg/images.yaml"
|
||||
# there are bits for image substitution in some of the ytt commands
|
||||
kbld --file "./${resource_name}/config/" --imgpkg-lock-output "./${resource_name}/.imgpkg/images.yml"
|
||||
|
||||
# generate a schema in each package directory
|
||||
echo_yellow "generating ./${resource_name}/schema-openapi.yaml"
|
||||
ytt \
|
||||
--file "${resource_name}/config/values.yaml" \
|
||||
--data-values-schema-inspect --output openapi-v3 > "${resource_name}/schema-openapi.yml"
|
||||
|
||||
# TODO:
|
||||
# push each package to the repository
|
||||
# note that I am hacking at this pattern to just get them to my dockerhub
|
||||
# this may or may not be the pattern we want when we push to a formal repository location
|
||||
# package_push_repo_location="${PACKAGE_REPO_HOST}/packages/${resource_name}:${PINNIPED_PACKAGE_VERSION}"
|
||||
package_push_repo_location="${PACKAGE_REPO_HOST}-package-${resource_name}:${PINNIPED_PACKAGE_VERSION}"
|
||||
echo_yellow "pushing package image: ${package_push_repo_location} ..."
|
||||
imgpkg push --bundle "${package_push_repo_location}" --file "./${resource_name}"
|
||||
|
||||
resource_package_version="${resource_name}.pinniped.dev"
|
||||
echo_yellow "generating ./${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/${PINNIPED_PACKAGE_VERSION}.yml"
|
||||
ytt \
|
||||
--file "${resource_name}/package-template.yml" \
|
||||
--data-value-file openapi="$(pwd)/${resource_name}/schema-openapi.yml" \
|
||||
--data-value package_version="${PINNIPED_PACKAGE_VERSION}" \
|
||||
--data-value package_image_repo="${package_push_repo_location}" > "${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/${PINNIPED_PACKAGE_VERSION}.yml"
|
||||
|
||||
echo_yellow "generating ./${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/metadata.yml"
|
||||
ytt \
|
||||
--file "${resource_name}/metadata.yml" \
|
||||
--data-value-file openapi="$(pwd)/${resource_name}/schema-openapi.yml" \
|
||||
--data-value package_version="${PINNIPED_PACKAGE_VERSION}" \
|
||||
--data-value package_image_repo="${package_push_repo_location}" > "${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/metadata.yml"
|
||||
|
||||
done
|
||||
|
||||
echo_yellow "generating ./${PACKAGE_REPOSITORY_DIR}/.imgpkg/images.yml"
|
||||
kbld --file "./${PACKAGE_REPOSITORY_DIR}/packages/" --imgpkg-lock-output "${PACKAGE_REPOSITORY_DIR}/.imgpkg/images.yml"
|
||||
package_repository_push_repo_location="${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||
echo_yellow "pushing package repository image: ${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}..."
|
||||
imgpkg push --bundle "${package_repository_push_repo_location}" --file "./${PACKAGE_REPOSITORY_DIR}"
|
||||
|
||||
echo_yellow "validating imgpkg package bundle contents..."
|
||||
imgpkg pull --bundle "${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}" --output "/tmp/${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||
ls -la "/tmp/${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||
|
||||
|
||||
echo_yellow "deploying PackageRepository..."
|
||||
PINNIPED_PACKGE_REPOSITORY_NAME="pinniped-package-repository"
|
||||
PINNIPED_PACKGE_REPOSITORY_FILE="packagerepository.${PINNIPED_PACKAGE_VERSION}.yml"
|
||||
echo -n "" > "${PINNIPED_PACKGE_REPOSITORY_FILE}"
|
||||
|
||||
cat <<EOT >> "${PINNIPED_PACKGE_REPOSITORY_FILE}"
|
||||
---
|
||||
apiVersion: packaging.carvel.dev/v1alpha1
|
||||
kind: PackageRepository
|
||||
metadata:
|
||||
name: "${PINNIPED_PACKGE_REPOSITORY_NAME}"
|
||||
spec:
|
||||
fetch:
|
||||
imgpkgBundle:
|
||||
image: "${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||
EOT
|
||||
|
||||
|
||||
# Now, gotta make this work. It'll be interesting if we can...
|
||||
kapp deploy --app "${PINNIPED_PACKGE_REPOSITORY_NAME}" --file "${PINNIPED_PACKGE_REPOSITORY_FILE}" -y
|
||||
kapp inspect --app "${PINNIPED_PACKGE_REPOSITORY_NAME}" --tree
|
||||
|
||||
sleep 2 # TODO: remove
|
||||
|
||||
# this is just a note to break this up, probably should use a separate ./deploy_stuff.sh file.
|
||||
# at this point, we are "consumers".
|
||||
# above we are packaging.
|
||||
# this would be separated out into another script or potentially
|
||||
# be on the user to craft (though we should likely provide something)
|
||||
echo_green "Package Installation...."
|
||||
|
||||
echo_yellow "deploying RBAC for use with pinniped PackageInstall..."
|
||||
|
||||
# TODO: obviously a mega-role that can do everything is not good. we need to scope this down to appropriate things.
|
||||
declare -a arr=("supervisor" "concierge")
|
||||
for resource_name in "${arr[@]}"
|
||||
do
|
||||
|
||||
NAMESPACE="${resource_name}-ns"
|
||||
PINNIPED_PACKAGE_RBAC_PREFIX="pinniped-package-rbac-${resource_name}"
|
||||
PINNIPED_PACKAGE_RBAC_FILE="./${PACKAGE_INSTALL_DIR}/${PINNIPED_PACKAGE_RBAC_PREFIX}-${resource_name}-rbac.yml"
|
||||
|
||||
echo -n "" > "${PINNIPED_PACKAGE_RBAC_FILE}"
|
||||
cat <<EOF >> "${PINNIPED_PACKAGE_RBAC_FILE}"
|
||||
# ---
|
||||
# apiVersion: v1
|
||||
# kind: Namespace
|
||||
# metadata:
|
||||
# name: "${NAMESPACE}" <--- "supervisor-ns" will cause other package install errors.
|
||||
---
|
||||
# ServiceAccount details from the file linked above
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||
# namespace: "${NAMESPACE}"
|
||||
namespace: default # --> sticking to default for everything for now.
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-role-superadmin-dangerous"
|
||||
rules:
|
||||
- apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-role-binding-superadmin-dangerous"
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||
# namespace: "${NAMESPACE}"
|
||||
namespace: default # --> sticking to default for everything for now.
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-role-superadmin-dangerous"
|
||||
|
||||
EOF
|
||||
|
||||
kapp deploy --app "${PINNIPED_PACKAGE_RBAC_PREFIX}" --file "${PINNIPED_PACKAGE_RBAC_FILE}" -y
|
||||
done
|
||||
|
||||
|
||||
#PINNIPED_PACKAGE_RBAC_FILE="./${PACKAGE_INSTALL_DIR}/${PINNIPED_PACKAGE_RBAC_PREFIX}-rbac.yml"
|
||||
## TODO: obviously a mega-role that can do everything is not good.
|
||||
#echo -n "" > "${PINNIPED_PACKAGE_RBAC_FILE}"
|
||||
#cat <<EOF >> "${PINNIPED_PACKAGE_RBAC_FILE}"
|
||||
#
|
||||
echo_yellow "deploying PackageInstall resources for pinniped supervisor and concierge packages..."
|
||||
for resource_name in "${arr[@]}"
|
||||
do
|
||||
|
||||
NAMESPACE="${resource_name}-ns"
|
||||
PINNIPED_PACKAGE_RBAC_PREFIX="pinniped-package-rbac-${resource_name}"
|
||||
RESOURCE_PACKGE_VERSION="${resource_name}.pinniped.dev"
|
||||
PACKAGE_INSTALL_FILE_NAME="./${PACKAGE_INSTALL_DIR}/${resource_name}-pkginstall.yml"
|
||||
SECRET_NAME="${resource_name}-package-install-secret"
|
||||
cat > "${PACKAGE_INSTALL_FILE_NAME}" << EOF
|
||||
---
|
||||
apiVersion: packaging.carvel.dev/v1alpha1
|
||||
kind: PackageInstall
|
||||
metadata:
|
||||
# name, does not have to be versioned, versionSelection.constraints below will handle
|
||||
name: "${resource_name}-package-install"
|
||||
# namespace: "${NAMESPACE}"
|
||||
namespace: default # --> sticking to default for everything for now.
|
||||
spec:
|
||||
serviceAccountName: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||
packageRef:
|
||||
refName: "${RESOURCE_PACKGE_VERSION}"
|
||||
versionSelection:
|
||||
constraints: "${PINNIPED_PACKAGE_VERSION}"
|
||||
values:
|
||||
- secretRef:
|
||||
name: "${SECRET_NAME}"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: "${SECRET_NAME}"
|
||||
stringData:
|
||||
values.yml: |
|
||||
---
|
||||
namespace: "${NAMESPACE}"
|
||||
app_name: "${resource_name}-app-awesomeness"
|
||||
replicas: 3
|
||||
EOF
|
||||
|
||||
KAPP_CONTROLLER_APP_NAME="${resource_name}-pkginstall"
|
||||
echo_yellow "deploying ${KAPP_CONTROLLER_APP_NAME}..."
|
||||
kapp deploy --app "${KAPP_CONTROLLER_APP_NAME}" --file "${PACKAGE_INSTALL_FILE_NAME}" -y
|
||||
|
||||
done
|
||||
|
||||
echo_yellow "verifying PackageInstall resources..."
|
||||
kubectl get PackageInstall -A | grep pinniped
|
||||
kubectl get secret -A | grep pinniped
|
||||
|
||||
echo_yellow "listing all package resources (PackageRepository, Package, PackageInstall)..."
|
||||
kubectl get pkgi && kubectl get pkgr && kubectl get pkg
|
||||
|
||||
echo_yellow "listing all kapp cli apps..."
|
||||
# list again what is installed so we can ensure we have everything
|
||||
kapp ls --all-namespaces
|
||||
|
||||
# these are fundamentally different than what kapp cli understands, unfortunately.
|
||||
# the term "app" is overloaded in Carvel and can mean two different things, based on
|
||||
# the use of kapp cli and kapp-controller on cluster
|
||||
echo_yellow "listing all kapp-controller apps..."
|
||||
kubectl get app --all-namespaces
|
||||
|
||||
# TODO:
|
||||
# update the deployment.yaml and remove the deployment-HACKED.yaml files
|
||||
# both are probably hacked a bit, so delete them and just get fresh from the ./deploy directory
|
||||
# then make sure REAL PINNIPED actually deploys.
|
||||
|
||||
|
||||
# In the end we should have:
|
||||
# docker pull benjaminapetersen/pinniped-package-repo:latest
|
||||
# docker pull benjaminapetersen/pinniped-package-repo-package-supervisor:0.25.0
|
||||
# docker pull benjaminapetersen/pinniped-package-repo-package-concierge:0.25.0
|
||||
|
||||
# echo_yellow "verifying RBAC resources created (namespace, serviceaccount, clusterrole, clusterrolebinding)..."
|
||||
# kubectl get ns -A | grep pinniped
|
||||
# kubectl get sa -A | grep pinniped
|
||||
# kubectl get ClusterRole -A | grep pinniped
|
||||
# kubectl get clusterrolebinding -A | grep pinniped
|
||||
|
||||
|
||||
# stuff
|
||||
kubectl get PackageRepository -A
|
||||
kubectl get Package -A
|
||||
kubectl get PackageInstall -A
|
420
deploy_carvel/build_and_deploy_for_integration_tests.sh
Executable file
420
deploy_carvel/build_and_deploy_for_integration_tests.sh
Executable file
@ -0,0 +1,420 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425
|
||||
set -e # immediately exit
|
||||
set -u # error if variables undefined
|
||||
set -o pipefail # prevent masking errors in a pipeline
|
||||
# set -x # print all executed commands to terminal
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
DEFAULT='\033[0m'
|
||||
|
||||
echo_yellow() {
|
||||
echo -e "${YELLOW}>> $@${DEFAULT}\n"
|
||||
# printf "${GREEN}$@${DEFAULT}"
|
||||
}
|
||||
|
||||
echo_green() {
|
||||
echo -e "${GREEN}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
echo_red() {
|
||||
echo -e "${RED}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
echo_blue() {
|
||||
echo -e "${BLUE}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
|
||||
# tag=$(uuidgen) # always a new tag to force K8s to reload the image on redeploy
|
||||
# build_and_deploy_for_integration_tests.sh 123455
|
||||
echo ""
|
||||
echo ""
|
||||
app=${1} # throw away, pattern is always to call scripts with 2 args
|
||||
tag=${2} # need to manually pass this, use the same from prepare-for-integreation-tests.sh
|
||||
echo_yellow "using tag: ${tag}"
|
||||
echo ""
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
# got a cluster?
|
||||
echo_yellow "Verify you have a functional kind cluster, otherwise this will fail..."
|
||||
# ./kind-with-registry.sh
|
||||
# got kapp-controller bits?
|
||||
kubectl get customresourcedefinitions
|
||||
echo_yellow "deploying kapp-controller..."
|
||||
kapp deploy --app kapp-controller --file https://github.com/vmware-tanzu/carvel-kapp-controller/releases/latest/download/release.yml -y
|
||||
kubectl get customresourcedefinitions
|
||||
|
||||
# this argument is given to kapp-controller by default
|
||||
# in the above deployment manfiest:
|
||||
# -packaging-global-namespace=kapp-controller-packaging-global
|
||||
# which means, PackageRepos and Packages ought be installed in this
|
||||
# namespace to be globally available by default, since
|
||||
# PackageRepos and Packages are namespaced resources.
|
||||
KAPP_CONTROLLER_GLOBAL_NAMESPACE="kapp-controller-packaging-global"
|
||||
|
||||
# START PINNIPED IMAGE, NOT PACKAGE -------------- >>>>
|
||||
# note: hack this into whatever
|
||||
# is currently storing the
|
||||
# pinniped image itself,
|
||||
# i think the default is fine
|
||||
# since we ran prepare-for-integration-test.sh
|
||||
# and it does the "kind load" on the
|
||||
# pinniped image
|
||||
# registry="pinniped.local" # Hack, but not what we really want: getpinniped/pinniped-server:latest
|
||||
registry="localhost:5001" # local registry setup via splicing in https://kind.sigs.k8s.io/docs/user/local-registry/
|
||||
repo="test/build"
|
||||
registry_repo="$registry/$repo"
|
||||
|
||||
|
||||
api_group_suffix="pinniped.dev"
|
||||
# END PINNIPED IMAGE, NOT PACKAGE -------------- >>>>
|
||||
|
||||
|
||||
# TODO: since I removed the deployments there is not much in the ./imgpkg/images.yaml output
|
||||
#
|
||||
# build images found in these directories.
|
||||
# make use of build.yaml files to specify how builds should work,
|
||||
# if we need it to be done.
|
||||
# kbld --file ./concierge/config --imgpkg-lock-output ./concierge/.imgpkg/images.yml
|
||||
|
||||
# this is used in the package-template.yml file for declaring where the package will live.
|
||||
# we need to know where these package images should live :)
|
||||
# REPO_HOST="1.2.3.4.fake.repo.host:5000"
|
||||
# PACKAGE_REPO_HOST="projects.registry.vmware.com/pinniped/pinniped-server"
|
||||
# PACKAGE_REPO_HOST="docker.io/benjaminapetersen/pinniped-package-repo"
|
||||
PACKAGE_REPO_HOST="benjaminapetersen/pinniped-package-repo"
|
||||
PINNIPED_PACKAGE_VERSION="0.25.0"
|
||||
|
||||
# TODO: cp ./deploy/supervisor.... into ./deploy_carvel/supervisor/config...
|
||||
# TODO: cp ./deploy/concierge.... into ./deploy_carvel/concierge/config...
|
||||
# -- we should copy this over, yeah?
|
||||
# NOTE: I did make changes to values.yaml to turn it into a values schema....
|
||||
|
||||
echo ""
|
||||
echo_yellow "cleaning ./package-repository..."
|
||||
PACKAGE_REPOSITORY_DIR="package-repository"
|
||||
rm -rf "${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}"
|
||||
mkdir -p "${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/.imgpkg"
|
||||
mkdir -p "${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/concierge.pinniped.dev"
|
||||
mkdir -p "${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/supervisor.pinniped.dev"
|
||||
|
||||
PACKAGE_INSTALL_DIR="temp_actual_deploy_resources"
|
||||
rm -rf "${SCRIPT_DIR}/${PACKAGE_INSTALL_DIR}"
|
||||
mkdir "${SCRIPT_DIR}/${PACKAGE_INSTALL_DIR}"
|
||||
|
||||
## TODO:
|
||||
## "${resource_name}/deployment.yml" vs "${resource_name}/deployment-HACKED.yml"
|
||||
## the real one has images.
|
||||
## - CURRENTLY the deployment.yaml files don't work, there is some error with pushing images.
|
||||
## come back to this later?
|
||||
declare -a arr=("supervisor" "concierge")
|
||||
for resource_name in "${arr[@]}"
|
||||
do
|
||||
echo ""
|
||||
echo_yellow "handling ${resource_name}..."
|
||||
|
||||
# just simple templating
|
||||
echo_yellow "generating ${resource_name}/.imgpkg/images.yaml"
|
||||
|
||||
# in order to run kbld to generate correct imgpkg lock files,
|
||||
# we must ytt render the templates and then pass the output to kbld
|
||||
ytt \
|
||||
--file "${SCRIPT_DIR}/${resource_name}/config/" | \
|
||||
kbld -f- --imgpkg-lock-output "${SCRIPT_DIR}/${resource_name}/.imgpkg/images.yml"
|
||||
|
||||
# generate a schema in each package directory
|
||||
echo_yellow "generating ${SCRIPT_DIR}/${resource_name}/schema-openapi.yaml"
|
||||
ytt \
|
||||
--file "${SCRIPT_DIR}/${resource_name}/config/values.yaml" \
|
||||
--data-values-schema-inspect --output openapi-v3 > "${SCRIPT_DIR}/${resource_name}/schema-openapi.yml"
|
||||
|
||||
# TODO:
|
||||
# push each package to the repository
|
||||
# note that I am hacking at this pattern to just get them to my dockerhub
|
||||
# this may or may not be the pattern we want when we push to a formal repository location
|
||||
# package_push_repo_location="${PACKAGE_REPO_HOST}/packages/${resource_name}:${PINNIPED_PACKAGE_VERSION}"
|
||||
package_push_repo_location="${PACKAGE_REPO_HOST}-package-${resource_name}:${PINNIPED_PACKAGE_VERSION}"
|
||||
echo_yellow "pushing package image: ${package_push_repo_location} ..."
|
||||
imgpkg push --bundle "${package_push_repo_location}" --file "${SCRIPT_DIR}/${resource_name}"
|
||||
|
||||
resource_package_version="${resource_name}.pinniped.dev"
|
||||
echo_yellow "generating ${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/${PINNIPED_PACKAGE_VERSION}.yml"
|
||||
ytt \
|
||||
--file "${SCRIPT_DIR}/${resource_name}/package-template.yml" \
|
||||
--data-value-file openapi="${SCRIPT_DIR}/${resource_name}/schema-openapi.yml" \
|
||||
--data-value package_version="${PINNIPED_PACKAGE_VERSION}" \
|
||||
--data-value package_image_repo="${package_push_repo_location}" > "${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/${PINNIPED_PACKAGE_VERSION}.yml"
|
||||
|
||||
echo_yellow "generating ${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/metadata.yml"
|
||||
ytt \
|
||||
--file "${SCRIPT_DIR}/${resource_name}/metadata.yml" \
|
||||
--data-value-file openapi="${SCRIPT_DIR}/${resource_name}/schema-openapi.yml" \
|
||||
--data-value package_version="${PINNIPED_PACKAGE_VERSION}" \
|
||||
--data-value package_image_repo="${package_push_repo_location}" > "${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/${resource_package_version}/metadata.yml"
|
||||
|
||||
done
|
||||
|
||||
echo_yellow "generating ${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/.imgpkg/images.yml"
|
||||
kbld --file "${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/packages/" --imgpkg-lock-output "${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}/.imgpkg/images.yml"
|
||||
package_repository_push_repo_location="${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||
echo_yellow "pushing package repository image: ${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}..."
|
||||
imgpkg push --bundle "${package_repository_push_repo_location}" --file "${SCRIPT_DIR}/${PACKAGE_REPOSITORY_DIR}"
|
||||
|
||||
echo_yellow "validating imgpkg package bundle contents..."
|
||||
imgpkg pull --bundle "${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}" --output "/tmp/${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||
ls -la "/tmp/${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||
|
||||
|
||||
echo_yellow "deploying PackageRepository..."
|
||||
PINNIPED_PACKAGE_REPOSITORY_NAME="pinniped-package-repository"
|
||||
PINNIPED_PACKAGE_REPOSITORY_FILE="packagerepository.${PINNIPED_PACKAGE_VERSION}.yml"
|
||||
echo -n "" > "${PINNIPED_PACKAGE_REPOSITORY_FILE}"
|
||||
|
||||
cat <<EOT >> "${PINNIPED_PACKAGE_REPOSITORY_FILE}"
|
||||
---
|
||||
apiVersion: packaging.carvel.dev/v1alpha1
|
||||
kind: PackageRepository
|
||||
metadata:
|
||||
name: "${PINNIPED_PACKAGE_REPOSITORY_NAME}"
|
||||
spec:
|
||||
fetch:
|
||||
imgpkgBundle:
|
||||
image: "${PACKAGE_REPO_HOST}:${PINNIPED_PACKAGE_VERSION}"
|
||||
EOT
|
||||
|
||||
|
||||
# Now, gotta make this work. It'll be interesting if we can...
|
||||
kapp deploy --app "${PINNIPED_PACKAGE_REPOSITORY_NAME}" --file "${PINNIPED_PACKAGE_REPOSITORY_FILE}" -y
|
||||
kapp inspect --app "${PINNIPED_PACKAGE_REPOSITORY_NAME}" --tree
|
||||
|
||||
sleep 2 # TODO: remove
|
||||
|
||||
# this is just a note to break this up, probably should use a separate ./deploy_stuff.sh file.
|
||||
# at this point, we are "consumers".
|
||||
# above we are packaging.
|
||||
# this would be separated out into another script or potentially
|
||||
# be on the user to craft (though we should likely provide something)
|
||||
echo_green "Package Installation...."
|
||||
|
||||
echo_yellow "deploying RBAC for use with pinniped PackageInstall..."
|
||||
|
||||
# TODO: obviously a mega-role that can do everything is not good. we need to scope this down to appropriate things.
|
||||
declare -a arr=("supervisor" "concierge")
|
||||
for resource_name in "${arr[@]}"
|
||||
do
|
||||
|
||||
NAMESPACE="${resource_name}-ns"
|
||||
PINNIPED_PACKAGE_RBAC_PREFIX="pinniped-package-rbac-${resource_name}"
|
||||
PINNIPED_PACKAGE_RBAC_FILE="${SCRIPT_DIR}/${PACKAGE_INSTALL_DIR}/${PINNIPED_PACKAGE_RBAC_PREFIX}-${resource_name}-rbac.yml"
|
||||
|
||||
echo -n "" > "${PINNIPED_PACKAGE_RBAC_FILE}"
|
||||
cat <<EOF >> "${PINNIPED_PACKAGE_RBAC_FILE}"
|
||||
# ---
|
||||
# apiVersion: v1
|
||||
# kind: Namespace
|
||||
# metadata:
|
||||
# name: "${NAMESPACE}" <--- "supervisor-ns" will cause other package install errors.
|
||||
---
|
||||
# ServiceAccount details from the file linked above
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||
# namespace: "${NAMESPACE}"
|
||||
namespace: default # --> sticking to default for everything for now.
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-role-superadmin-dangerous"
|
||||
rules:
|
||||
- apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-role-binding-superadmin-dangerous"
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||
# namespace: "${NAMESPACE}"
|
||||
namespace: default # --> sticking to default for everything for now.
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: "${PINNIPED_PACKAGE_RBAC_PREFIX}-role-superadmin-dangerous"
|
||||
|
||||
EOF
|
||||
|
||||
kapp deploy --app "${PINNIPED_PACKAGE_RBAC_PREFIX}" --file "${PINNIPED_PACKAGE_RBAC_FILE}" -y
|
||||
done
|
||||
|
||||
|
||||
#PINNIPED_PACKAGE_RBAC_FILE="./${PACKAGE_INSTALL_DIR}/${PINNIPED_PACKAGE_RBAC_PREFIX}-rbac.yml"
|
||||
## TODO: obviously a mega-role that can do everything is not good.
|
||||
#echo -n "" > "${PINNIPED_PACKAGE_RBAC_FILE}"
|
||||
#cat <<EOF >> "${PINNIPED_PACKAGE_RBAC_FILE}"
|
||||
#
|
||||
echo_yellow "deploying supervisor PackageInstall resources..."
|
||||
resource_name="supervisor"
|
||||
NAMESPACE="${resource_name}-ns"
|
||||
PINNIPED_PACKAGE_RBAC_PREFIX="pinniped-package-rbac-${resource_name}"
|
||||
RESOURCE_PACKGE_VERSION="${resource_name}.pinniped.dev"
|
||||
PACKAGE_INSTALL_FILE_NAME="${SCRIPT_DIR}/${PACKAGE_INSTALL_DIR}/${resource_name}-pkginstall.yml"
|
||||
SECRET_NAME="${resource_name}-package-install-secret"
|
||||
|
||||
# from prepare-for-integration-test.sh
|
||||
supervisor_app_name="pinniped-supervisor"
|
||||
supervisor_namespace="supervisor"
|
||||
supervisor_custom_labels="{mySupervisorCustomLabelName: mySupervisorCustomLabelValue}"
|
||||
log_level="debug"
|
||||
service_https_nodeport_port="443"
|
||||
service_https_nodeport_nodeport="31243"
|
||||
service_https_clusterip_port="443"
|
||||
cat > "${PACKAGE_INSTALL_FILE_NAME}" << EOF
|
||||
---
|
||||
apiVersion: packaging.carvel.dev/v1alpha1
|
||||
kind: PackageInstall
|
||||
metadata:
|
||||
# name, does not have to be versioned, versionSelection.constraints below will handle
|
||||
name: "${resource_name}-package-install"
|
||||
# namespace: "${NAMESPACE}"
|
||||
namespace: default # --> sticking to default for everything for now.
|
||||
spec:
|
||||
serviceAccountName: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||
packageRef:
|
||||
refName: "${RESOURCE_PACKGE_VERSION}"
|
||||
versionSelection:
|
||||
constraints: "${PINNIPED_PACKAGE_VERSION}"
|
||||
values:
|
||||
- secretRef:
|
||||
name: "${SECRET_NAME}"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: "${SECRET_NAME}"
|
||||
stringData:
|
||||
values.yml: |
|
||||
---
|
||||
app_name: $supervisor_app_name
|
||||
namespace: $supervisor_namespace
|
||||
api_group_suffix: $api_group_suffix
|
||||
image_repo: $registry_repo
|
||||
image_tag: $tag
|
||||
log_level: $log_level
|
||||
|
||||
service_https_nodeport_port: $service_https_nodeport_port
|
||||
service_https_nodeport_nodeport: $service_https_nodeport_nodeport
|
||||
service_https_clusterip_port: $service_https_clusterip_port
|
||||
EOF
|
||||
|
||||
KAPP_CONTROLLER_APP_NAME="${resource_name}-pkginstall"
|
||||
echo_yellow "deploying ${KAPP_CONTROLLER_APP_NAME}..."
|
||||
kapp deploy --app "${KAPP_CONTROLLER_APP_NAME}" --file "${PACKAGE_INSTALL_FILE_NAME}" -y
|
||||
# end supervisor
|
||||
|
||||
# concierge
|
||||
echo_yellow "deploying concierge PackageInstall resources..."
|
||||
resource_name="concierge"
|
||||
NAMESPACE="${resource_name}-ns"
|
||||
PINNIPED_PACKAGE_RBAC_PREFIX="pinniped-package-rbac-${resource_name}"
|
||||
RESOURCE_PACKGE_VERSION="${resource_name}.pinniped.dev"
|
||||
PACKAGE_INSTALL_FILE_NAME="${SCRIPT_DIR}/${PACKAGE_INSTALL_DIR}/${resource_name}-pkginstall.yml"
|
||||
SECRET_NAME="${resource_name}-package-install-secret"
|
||||
|
||||
# from prepare-for-integration-tests.sh
|
||||
concierge_app_name="pinniped-concierge"
|
||||
concierge_namespace="concierge"
|
||||
webhook_url="https://local-user-authenticator.local-user-authenticator.svc/authenticate"
|
||||
webhook_ca_bundle="$(kubectl get secret local-user-authenticator-tls-serving-certificate --namespace local-user-authenticator -o 'jsonpath={.data.caCertificate}')"
|
||||
discovery_url="$(TERM=dumb kubectl cluster-info | awk '/master|control plane/ {print $NF}')"
|
||||
concierge_custom_labels="{myConciergeCustomLabelName: myConciergeCustomLabelValue}"
|
||||
log_level="debug"
|
||||
cat > "${PACKAGE_INSTALL_FILE_NAME}" << EOF
|
||||
---
|
||||
apiVersion: packaging.carvel.dev/v1alpha1
|
||||
kind: PackageInstall
|
||||
metadata:
|
||||
# name, does not have to be versioned, versionSelection.constraints below will handle
|
||||
name: "${resource_name}-package-install"
|
||||
# namespace: "${NAMESPACE}"
|
||||
namespace: default # --> sticking to default for everything for now.
|
||||
spec:
|
||||
serviceAccountName: "${PINNIPED_PACKAGE_RBAC_PREFIX}-sa-superadmin-dangerous"
|
||||
packageRef:
|
||||
refName: "${RESOURCE_PACKGE_VERSION}"
|
||||
versionSelection:
|
||||
constraints: "${PINNIPED_PACKAGE_VERSION}"
|
||||
values:
|
||||
- secretRef:
|
||||
name: "${SECRET_NAME}"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: "${SECRET_NAME}"
|
||||
stringData:
|
||||
values.yml: |
|
||||
---
|
||||
app_name: $concierge_app_name
|
||||
namespace: $concierge_namespace
|
||||
api_group_suffix: $api_group_suffix
|
||||
log_level: $log_level
|
||||
|
||||
image_repo: $registry_repo
|
||||
image_tag: $tag
|
||||
EOF
|
||||
|
||||
KAPP_CONTROLLER_APP_NAME="${resource_name}-pkginstall"
|
||||
echo_yellow "deploying ${KAPP_CONTROLLER_APP_NAME}..."
|
||||
kapp deploy --app "${KAPP_CONTROLLER_APP_NAME}" --file "${PACKAGE_INSTALL_FILE_NAME}" -y
|
||||
# end concierge
|
||||
|
||||
echo_yellow "verifying PackageInstall resources..."
|
||||
kubectl get PackageInstall -A | grep pinniped
|
||||
kubectl get secret -A | grep pinniped
|
||||
|
||||
echo_yellow "listing all package resources (PackageRepository, Package, PackageInstall)..."
|
||||
kubectl get pkgi && kubectl get pkgr && kubectl get pkg
|
||||
|
||||
echo_yellow "listing all kapp cli apps..."
|
||||
# list again what is installed so we can ensure we have everything
|
||||
kapp ls --all-namespaces
|
||||
|
||||
# these are fundamentally different than what kapp cli understands, unfortunately.
|
||||
# the term "app" is overloaded in Carvel and can mean two different things, based on
|
||||
# the use of kapp cli and kapp-controller on cluster
|
||||
echo_yellow "listing all kapp-controller apps..."
|
||||
kubectl get app --all-namespaces
|
||||
|
||||
# TODO:
|
||||
# update the deployment.yaml and remove the deployment-HACKED.yaml files
|
||||
# both are probably hacked a bit, so delete them and just get fresh from the ./deploy directory
|
||||
# then make sure REAL PINNIPED actually deploys.
|
||||
|
||||
|
||||
# In the end we should have:
|
||||
# docker pull benjaminapetersen/pinniped-package-repo:latest
|
||||
# docker pull benjaminapetersen/pinniped-package-repo-package-supervisor:0.25.0
|
||||
# docker pull benjaminapetersen/pinniped-package-repo-package-concierge:0.25.0
|
||||
|
||||
# echo_yellow "verifying RBAC resources created (namespace, serviceaccount, clusterrole, clusterrolebinding)..."
|
||||
# kubectl get ns -A | grep pinniped
|
||||
# kubectl get sa -A | grep pinniped
|
||||
# kubectl get ClusterRole -A | grep pinniped
|
||||
# kubectl get clusterrolebinding -A | grep pinniped
|
||||
|
||||
|
||||
# stuff
|
||||
kubectl get PackageRepository -A
|
||||
kubectl get Package -A
|
||||
kubectl get PackageInstall -A
|
11
deploy_carvel/concierge/.imgpkg/images.yml
Normal file
11
deploy_carvel/concierge/.imgpkg/images.yml
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
apiVersion: imgpkg.carvel.dev/v1alpha1
|
||||
images:
|
||||
- annotations:
|
||||
kbld.carvel.dev/id: projects.registry.vmware.com/pinniped/pinniped-server:latest
|
||||
kbld.carvel.dev/origins: |
|
||||
- resolved:
|
||||
tag: latest
|
||||
url: projects.registry.vmware.com/pinniped/pinniped-server:latest
|
||||
image: projects.registry.vmware.com/pinniped/pinniped-server@sha256:a92183de893eb0b1850cc3a1d33306b96ba2cdb72a8a49c6493a58c01b4fa9cd
|
||||
kind: ImagesLock
|
23
deploy_carvel/concierge/build.yaml
Normal file
23
deploy_carvel/concierge/build.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
#@ load("@ytt:data", "data")
|
||||
---
|
||||
apiVersion: kbld.k14s.io/v1alpha1
|
||||
kind: Config
|
||||
minimumRequiredVersion: 0.31.0 #! minimum version of kbld. We probably don't need to specify.
|
||||
overrides:
|
||||
#! TODO: in the pinniped yamls, this is provided by values.yaml, not declared in the deployment.
|
||||
#! we should assess if we want to leave it there or move it to this form of configuration.
|
||||
- image: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
newImage: #@ data.values.image_repo
|
||||
|
||||
|
||||
|
||||
|
||||
#! I don't think we need any of these (until we need them 😊). IE, don't use prematurely.
|
||||
#! searchRules: ... # for searching input files to find container images
|
||||
#! overrides: ... # overrides to apply to container images before resolving or building
|
||||
#! sources: ... # source/content of a container image
|
||||
#! destinations: ... # where to push built images
|
||||
#!
|
||||
#!
|
||||
#! source: TODO: we may need this at least to specify that we want kbld to build
|
||||
#! a set of container images that are found in our package config yaml files.
|
3
deploy_carvel/concierge/config/README.md
Normal file
3
deploy_carvel/concierge/config/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Pinniped Concierge Deployment
|
||||
|
||||
See [the how-to guide for details](https://pinniped.dev/docs/howto/install-concierge/).
|
@ -0,0 +1,176 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: jwtauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
names:
|
||||
categories:
|
||||
- pinniped
|
||||
- pinniped-authenticator
|
||||
- pinniped-authenticators
|
||||
kind: JWTAuthenticator
|
||||
listKind: JWTAuthenticatorList
|
||||
plural: jwtauthenticators
|
||||
singular: jwtauthenticator
|
||||
scope: Cluster
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.issuer
|
||||
name: Issuer
|
||||
type: string
|
||||
- jsonPath: .spec.audience
|
||||
name: Audience
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: "JWTAuthenticator describes the configuration of a JWT authenticator.
|
||||
\n Upon receiving a signed JWT, a JWTAuthenticator will performs some validation
|
||||
on it (e.g., valid signature, existence of claims, etc.) and extract the
|
||||
username and groups from the token."
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec for configuring the authenticator.
|
||||
properties:
|
||||
audience:
|
||||
description: Audience is the required value of the "aud" JWT claim.
|
||||
minLength: 1
|
||||
type: string
|
||||
claims:
|
||||
description: Claims allows customization of the claims that will be
|
||||
mapped to user identity for Kubernetes access.
|
||||
properties:
|
||||
groups:
|
||||
description: Groups is the name of the claim which should be read
|
||||
to extract the user's group membership from the JWT token. When
|
||||
not specified, it will default to "groups".
|
||||
type: string
|
||||
username:
|
||||
description: Username is the name of the claim which should be
|
||||
read to extract the username from the JWT token. When not specified,
|
||||
it will default to "username".
|
||||
type: string
|
||||
type: object
|
||||
issuer:
|
||||
description: Issuer is the OIDC issuer URL that will be used to discover
|
||||
public signing keys. Issuer is also used to validate the "iss" JWT
|
||||
claim.
|
||||
minLength: 1
|
||||
pattern: ^https://
|
||||
type: string
|
||||
tls:
|
||||
description: TLS configuration for communicating with the OIDC provider.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||
If omitted, a default set of system roots will be trusted.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- audience
|
||||
- issuer
|
||||
type: object
|
||||
status:
|
||||
description: Status of the authenticator.
|
||||
properties:
|
||||
conditions:
|
||||
description: Represents the observations of the authenticator's current
|
||||
state.
|
||||
items:
|
||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||
type added in Kubernetes 1.19). In a future API version we can
|
||||
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time the condition
|
||||
transitioned from one status to another. This should be when
|
||||
the underlying condition changed. If that is not known, then
|
||||
using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message indicating
|
||||
details about the transition. This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation
|
||||
that the condition was set based upon. For instance, if .metadata.generation
|
||||
is currently 12, but the .status.conditions[x].observedGeneration
|
||||
is 9, the condition is out of date with respect to the current
|
||||
state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier indicating
|
||||
the reason for the condition's last transition. Producers
|
||||
of specific condition types may define expected values and
|
||||
meanings for this field, and whether the values are considered
|
||||
a guaranteed API. The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
--- Many .condition.type values are consistent across resources
|
||||
like Available, but because arbitrary conditions can be useful
|
||||
(see .node.status.conditions), the ability to deconflict is
|
||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
@ -0,0 +1,149 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: webhookauthenticators.authentication.concierge.pinniped.dev
|
||||
spec:
|
||||
group: authentication.concierge.pinniped.dev
|
||||
names:
|
||||
categories:
|
||||
- pinniped
|
||||
- pinniped-authenticator
|
||||
- pinniped-authenticators
|
||||
kind: WebhookAuthenticator
|
||||
listKind: WebhookAuthenticatorList
|
||||
plural: webhookauthenticators
|
||||
singular: webhookauthenticator
|
||||
scope: Cluster
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.endpoint
|
||||
name: Endpoint
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: WebhookAuthenticator describes the configuration of a webhook
|
||||
authenticator.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec for configuring the authenticator.
|
||||
properties:
|
||||
endpoint:
|
||||
description: Webhook server endpoint URL.
|
||||
minLength: 1
|
||||
pattern: ^https://
|
||||
type: string
|
||||
tls:
|
||||
description: TLS configuration.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||
If omitted, a default set of system roots will be trusted.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- endpoint
|
||||
type: object
|
||||
status:
|
||||
description: Status of the authenticator.
|
||||
properties:
|
||||
conditions:
|
||||
description: Represents the observations of the authenticator's current
|
||||
state.
|
||||
items:
|
||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||
type added in Kubernetes 1.19). In a future API version we can
|
||||
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time the condition
|
||||
transitioned from one status to another. This should be when
|
||||
the underlying condition changed. If that is not known, then
|
||||
using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message indicating
|
||||
details about the transition. This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation
|
||||
that the condition was set based upon. For instance, if .metadata.generation
|
||||
is currently 12, but the .status.conditions[x].observedGeneration
|
||||
is 9, the condition is out of date with respect to the current
|
||||
state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier indicating
|
||||
the reason for the condition's last transition. Producers
|
||||
of specific condition types may define expected values and
|
||||
meanings for this field, and whether the values are considered
|
||||
a guaranteed API. The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
--- Many .condition.type values are consistent across resources
|
||||
like Available, but because arbitrary conditions can be useful
|
||||
(see .node.status.conditions), the ability to deconflict is
|
||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
@ -0,0 +1,264 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: credentialissuers.config.concierge.pinniped.dev
|
||||
spec:
|
||||
group: config.concierge.pinniped.dev
|
||||
names:
|
||||
categories:
|
||||
- pinniped
|
||||
kind: CredentialIssuer
|
||||
listKind: CredentialIssuerList
|
||||
plural: credentialissuers
|
||||
singular: credentialissuer
|
||||
scope: Cluster
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.impersonationProxy.mode
|
||||
name: ProxyMode
|
||||
type: string
|
||||
- jsonPath: .status.strategies[?(@.status == "Success")].type
|
||||
name: DefaultStrategy
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: CredentialIssuer describes the configuration and status of the
|
||||
Pinniped Concierge credential issuer.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec describes the intended configuration of the Concierge.
|
||||
properties:
|
||||
impersonationProxy:
|
||||
description: ImpersonationProxy describes the intended configuration
|
||||
of the Concierge impersonation proxy.
|
||||
properties:
|
||||
externalEndpoint:
|
||||
description: "ExternalEndpoint describes the HTTPS endpoint where
|
||||
the proxy will be exposed. If not set, the proxy will be served
|
||||
using the external name of the LoadBalancer service or the cluster
|
||||
service DNS name. \n This field must be non-empty when spec.impersonationProxy.service.type
|
||||
is \"None\"."
|
||||
type: string
|
||||
mode:
|
||||
description: 'Mode configures whether the impersonation proxy
|
||||
should be started: - "disabled" explicitly disables the impersonation
|
||||
proxy. This is the default. - "enabled" explicitly enables the
|
||||
impersonation proxy. - "auto" enables or disables the impersonation
|
||||
proxy based upon the cluster in which it is running.'
|
||||
enum:
|
||||
- auto
|
||||
- enabled
|
||||
- disabled
|
||||
type: string
|
||||
service:
|
||||
default:
|
||||
type: LoadBalancer
|
||||
description: Service describes the configuration of the Service
|
||||
provisioned to expose the impersonation proxy to clients.
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Annotations specifies zero or more key/value
|
||||
pairs to set as annotations on the provisioned Service.
|
||||
type: object
|
||||
loadBalancerIP:
|
||||
description: LoadBalancerIP specifies the IP address to set
|
||||
in the spec.loadBalancerIP field of the provisioned Service.
|
||||
This is not supported on all cloud providers.
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
type: string
|
||||
type:
|
||||
default: LoadBalancer
|
||||
description: "Type specifies the type of Service to provision
|
||||
for the impersonation proxy. \n If the type is \"None\",
|
||||
then the \"spec.impersonationProxy.externalEndpoint\" field
|
||||
must be set to a non-empty value so that the Concierge can
|
||||
properly advertise the endpoint in the CredentialIssuer's
|
||||
status."
|
||||
enum:
|
||||
- LoadBalancer
|
||||
- ClusterIP
|
||||
- None
|
||||
type: string
|
||||
type: object
|
||||
tls:
|
||||
description: "TLS contains information about how the Concierge
|
||||
impersonation proxy should serve TLS. \n If this field is empty,
|
||||
the impersonation proxy will generate its own TLS certificate."
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: X.509 Certificate Authority (base64-encoded PEM
|
||||
bundle). Used to advertise the CA bundle for the impersonation
|
||||
proxy endpoint.
|
||||
type: string
|
||||
secretName:
|
||||
description: SecretName is the name of a Secret in the same
|
||||
namespace, of type `kubernetes.io/tls`, which contains the
|
||||
TLS serving certificate for the Concierge impersonation
|
||||
proxy endpoint.
|
||||
minLength: 1
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- mode
|
||||
- service
|
||||
type: object
|
||||
required:
|
||||
- impersonationProxy
|
||||
type: object
|
||||
status:
|
||||
description: CredentialIssuerStatus describes the status of the Concierge.
|
||||
properties:
|
||||
kubeConfigInfo:
|
||||
description: Information needed to form a valid Pinniped-based kubeconfig
|
||||
using this credential issuer. This field is deprecated and will
|
||||
be removed in a future version.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: The K8s API server CA bundle.
|
||||
minLength: 1
|
||||
type: string
|
||||
server:
|
||||
description: The K8s API server URL.
|
||||
minLength: 1
|
||||
pattern: ^https://|^http://
|
||||
type: string
|
||||
required:
|
||||
- certificateAuthorityData
|
||||
- server
|
||||
type: object
|
||||
strategies:
|
||||
description: List of integration strategies that were attempted by
|
||||
Pinniped.
|
||||
items:
|
||||
description: CredentialIssuerStrategy describes the status of an
|
||||
integration strategy that was attempted by Pinniped.
|
||||
properties:
|
||||
frontend:
|
||||
description: Frontend describes how clients can connect using
|
||||
this strategy.
|
||||
properties:
|
||||
impersonationProxyInfo:
|
||||
description: ImpersonationProxyInfo describes the parameters
|
||||
for the impersonation proxy on this Concierge. This field
|
||||
is only set when Type is "ImpersonationProxy".
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: CertificateAuthorityData is the base64-encoded
|
||||
PEM CA bundle of the impersonation proxy.
|
||||
minLength: 1
|
||||
type: string
|
||||
endpoint:
|
||||
description: Endpoint is the HTTPS endpoint of the impersonation
|
||||
proxy.
|
||||
minLength: 1
|
||||
pattern: ^https://
|
||||
type: string
|
||||
required:
|
||||
- certificateAuthorityData
|
||||
- endpoint
|
||||
type: object
|
||||
tokenCredentialRequestInfo:
|
||||
description: TokenCredentialRequestAPIInfo describes the
|
||||
parameters for the TokenCredentialRequest API on this
|
||||
Concierge. This field is only set when Type is "TokenCredentialRequestAPI".
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: CertificateAuthorityData is the base64-encoded
|
||||
Kubernetes API server CA bundle.
|
||||
minLength: 1
|
||||
type: string
|
||||
server:
|
||||
description: Server is the Kubernetes API server URL.
|
||||
minLength: 1
|
||||
pattern: ^https://|^http://
|
||||
type: string
|
||||
required:
|
||||
- certificateAuthorityData
|
||||
- server
|
||||
type: object
|
||||
type:
|
||||
description: Type describes which frontend mechanism clients
|
||||
can use with a strategy.
|
||||
enum:
|
||||
- TokenCredentialRequestAPI
|
||||
- ImpersonationProxy
|
||||
type: string
|
||||
required:
|
||||
- type
|
||||
type: object
|
||||
lastUpdateTime:
|
||||
description: When the status was last checked.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Human-readable description of the current status.
|
||||
minLength: 1
|
||||
type: string
|
||||
reason:
|
||||
description: Reason for the current status.
|
||||
enum:
|
||||
- Listening
|
||||
- Pending
|
||||
- Disabled
|
||||
- ErrorDuringSetup
|
||||
- CouldNotFetchKey
|
||||
- CouldNotGetClusterInfo
|
||||
- FetchedKey
|
||||
type: string
|
||||
status:
|
||||
description: Status of the attempted integration strategy.
|
||||
enum:
|
||||
- Success
|
||||
- Error
|
||||
type: string
|
||||
type:
|
||||
description: Type of integration attempted.
|
||||
enum:
|
||||
- KubeClusterSigningCertificate
|
||||
- ImpersonationProxy
|
||||
type: string
|
||||
required:
|
||||
- lastUpdateTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
required:
|
||||
- strategies
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
360
deploy_carvel/concierge/config/deployment.yaml
Normal file
360
deploy_carvel/concierge/config/deployment.yaml
Normal file
@ -0,0 +1,360 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
#@ load("@ytt:json", "json")
|
||||
#@ load("helpers.lib.yaml", "defaultLabel", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "getAndValidateLogLevel", "pinnipedDevAPIGroupWithPrefix")
|
||||
#@ load("@ytt:template", "template")
|
||||
|
||||
#@ if not data.values.into_namespace:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: #@ data.values.namespace
|
||||
labels:
|
||||
_: #@ template.replace(labels())
|
||||
#! When deploying onto a cluster which has PSAs enabled by default for namespaces,
|
||||
#! effectively disable them for this namespace. The kube-cert-agent Deployment's pod
|
||||
#! created by the Concierge in this namespace needs to be able to perform privileged
|
||||
#! actions. The regular Concierge pod containers created by the Deployment below do
|
||||
#! not need special privileges and are marked as such in their securityContext settings.
|
||||
pod-security.kubernetes.io/enforce: privileged
|
||||
#@ end
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
annotations:
|
||||
#! we need to create this service account before we create the secret
|
||||
kapp.k14s.io/change-group: "impersonation-proxy.concierge.pinniped.dev/serviceaccount"
|
||||
secrets: #! make sure the token controller does not create any other secrets
|
||||
- name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("config")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
data:
|
||||
#! If names.apiService is changed in this ConfigMap, must also change name of the ClusterIP Service resource below.
|
||||
#@yaml/text-templated-strings
|
||||
pinniped.yaml: |
|
||||
discovery:
|
||||
url: (@= data.values.discovery_url or "null" @)
|
||||
api:
|
||||
servingCertificate:
|
||||
durationSeconds: (@= str(data.values.api_serving_certificate_duration_seconds) @)
|
||||
renewBeforeSeconds: (@= str(data.values.api_serving_certificate_renew_before_seconds) @)
|
||||
apiGroupSuffix: (@= data.values.api_group_suffix @)
|
||||
# aggregatedAPIServerPort may be set here, although other YAML references to the default port (10250) may also need to be updated
|
||||
# impersonationProxyServerPort may be set here, although other YAML references to the default port (8444) may also need to be updated
|
||||
names:
|
||||
servingCertificateSecret: (@= defaultResourceNameWithSuffix("api-tls-serving-certificate") @)
|
||||
credentialIssuer: (@= defaultResourceNameWithSuffix("config") @)
|
||||
apiService: (@= defaultResourceNameWithSuffix("api") @)
|
||||
impersonationLoadBalancerService: (@= defaultResourceNameWithSuffix("impersonation-proxy-load-balancer") @)
|
||||
impersonationClusterIPService: (@= defaultResourceNameWithSuffix("impersonation-proxy-cluster-ip") @)
|
||||
impersonationTLSCertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-tls-serving-certificate") @)
|
||||
impersonationCACertificateSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-ca-certificate") @)
|
||||
impersonationSignerSecret: (@= defaultResourceNameWithSuffix("impersonation-proxy-signer-ca-certificate") @)
|
||||
agentServiceAccount: (@= defaultResourceNameWithSuffix("kube-cert-agent") @)
|
||||
labels: (@= json.encode(labels()).rstrip() @)
|
||||
kubeCertAgent:
|
||||
namePrefix: (@= defaultResourceNameWithSuffix("kube-cert-agent-") @)
|
||||
(@ if data.values.kube_cert_agent_image: @)
|
||||
image: (@= data.values.kube_cert_agent_image @)
|
||||
(@ else: @)
|
||||
(@ if data.values.image_digest: @)
|
||||
image: (@= data.values.image_repo + "@" + data.values.image_digest @)
|
||||
(@ else: @)
|
||||
image: (@= data.values.image_repo + ":" + data.values.image_tag @)
|
||||
(@ end @)
|
||||
(@ end @)
|
||||
(@ if data.values.image_pull_dockerconfigjson: @)
|
||||
imagePullSecrets:
|
||||
- image-pull-secret
|
||||
(@ end @)
|
||||
(@ if data.values.log_level or data.values.deprecated_log_format: @)
|
||||
log:
|
||||
(@ if data.values.log_level: @)
|
||||
level: (@= getAndValidateLogLevel() @)
|
||||
(@ end @)
|
||||
(@ if data.values.deprecated_log_format: @)
|
||||
format: (@= data.values.deprecated_log_format @)
|
||||
(@ end @)
|
||||
(@ end @)
|
||||
---
|
||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: image-pull-secret
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
data:
|
||||
.dockerconfigjson: #@ data.values.image_pull_dockerconfigjson
|
||||
#@ end
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
spec:
|
||||
replicas: #@ data.values.replicas
|
||||
selector:
|
||||
#! In hindsight, this should have been deploymentPodLabel(), but this field is immutable so changing it would break upgrades.
|
||||
matchLabels: #@ defaultLabel()
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
#! This has always included defaultLabel(), which is used by this Deployment's selector.
|
||||
_: #@ template.replace(defaultLabel())
|
||||
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
|
||||
#! without accidentally selecting any other Deployment's Pods, especially the kube cert agent Deployment's Pods.
|
||||
_: #@ template.replace(deploymentPodLabel())
|
||||
annotations:
|
||||
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: #@ data.values.run_as_user
|
||||
runAsGroup: #@ data.values.run_as_group
|
||||
serviceAccountName: #@ defaultResourceName()
|
||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||
imagePullSecrets:
|
||||
- name: image-pull-secret
|
||||
#@ end
|
||||
containers:
|
||||
- name: #@ defaultResourceName()
|
||||
#@ if data.values.image_digest:
|
||||
image: #@ data.values.image_repo + "@" + data.values.image_digest
|
||||
#@ else:
|
||||
image: #@ data.values.image_repo + ":" + data.values.image_tag
|
||||
#@ end
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: [ "ALL" ]
|
||||
#! seccompProfile was introduced in Kube v1.19. Using it on an older Kube version will result in a
|
||||
#! kubectl validation error when installing via `kubectl apply`, which can be ignored using kubectl's
|
||||
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
||||
seccompProfile:
|
||||
type: "RuntimeDefault"
|
||||
resources:
|
||||
requests:
|
||||
cpu: "100m"
|
||||
memory: "128Mi"
|
||||
limits:
|
||||
cpu: "100m"
|
||||
memory: "128Mi"
|
||||
command:
|
||||
- pinniped-concierge
|
||||
- --config=/etc/config/pinniped.yaml
|
||||
- --downward-api-path=/etc/podinfo
|
||||
volumeMounts:
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- name: config-volume
|
||||
mountPath: /etc/config
|
||||
readOnly: true
|
||||
- name: podinfo
|
||||
mountPath: /etc/podinfo
|
||||
readOnly: true
|
||||
- name: impersonation-proxy
|
||||
mountPath: /var/run/secrets/impersonation-proxy.concierge.pinniped.dev/serviceaccount
|
||||
readOnly: true
|
||||
env:
|
||||
#@ if data.values.https_proxy:
|
||||
- name: HTTPS_PROXY
|
||||
value: #@ data.values.https_proxy
|
||||
#@ end
|
||||
#@ if data.values.https_proxy and data.values.no_proxy:
|
||||
- name: NO_PROXY
|
||||
value: #@ data.values.no_proxy
|
||||
#@ end
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10250
|
||||
scheme: HTTPS
|
||||
initialDelaySeconds: 2
|
||||
timeoutSeconds: 15
|
||||
periodSeconds: 10
|
||||
failureThreshold: 5
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 10250
|
||||
scheme: HTTPS
|
||||
initialDelaySeconds: 2
|
||||
timeoutSeconds: 3
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir:
|
||||
medium: Memory
|
||||
sizeLimit: 100Mi
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: #@ defaultResourceNameWithSuffix("config")
|
||||
- name: impersonation-proxy
|
||||
secret:
|
||||
secretName: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||
items: #! make sure our pod does not start until the token controller has a chance to populate the secret
|
||||
- key: token
|
||||
path: token
|
||||
- name: podinfo
|
||||
downwardAPI:
|
||||
items:
|
||||
- path: "labels"
|
||||
fieldRef:
|
||||
fieldPath: metadata.labels
|
||||
- path: "name"
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- path: "namespace"
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
tolerations:
|
||||
- key: CriticalAddonsOnly
|
||||
operator: Exists
|
||||
- key: node-role.kubernetes.io/master #! Allow running on master nodes too (name deprecated by kubernetes 1.20).
|
||||
effect: NoSchedule
|
||||
- key: node-role.kubernetes.io/control-plane #! The new name for these nodes as of Kubernetes 1.24.
|
||||
effect: NoSchedule
|
||||
#! "system-cluster-critical" cannot be used outside the kube-system namespace until Kubernetes >= 1.17,
|
||||
#! so we skip setting this for now (see https://github.com/kubernetes/kubernetes/issues/60596).
|
||||
#!priorityClassName: system-cluster-critical
|
||||
#! This will help make sure our multiple pods run on different nodes, making
|
||||
#! our deployment "more" "HA".
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 50
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels: #@ deploymentPodLabel()
|
||||
topologyKey: kubernetes.io/hostname
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
#! If name is changed, must also change names.apiService in the ConfigMap above and spec.service.name in the APIService below.
|
||||
name: #@ defaultResourceNameWithSuffix("api")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||
annotations:
|
||||
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector: #@ deploymentPodLabel()
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
targetPort: 10250
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("proxy")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||
annotations:
|
||||
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector: #@ deploymentPodLabel()
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
targetPort: 8444
|
||||
---
|
||||
apiVersion: apiregistration.k8s.io/v1
|
||||
kind: APIService
|
||||
metadata:
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("v1alpha1.login.concierge")
|
||||
labels: #@ labels()
|
||||
spec:
|
||||
version: v1alpha1
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("login.concierge")
|
||||
groupPriorityMinimum: 9900
|
||||
versionPriority: 15
|
||||
#! caBundle: Do not include this key here. Starts out null, will be updated/owned by the golang code.
|
||||
service:
|
||||
name: #@ defaultResourceNameWithSuffix("api")
|
||||
namespace: #@ namespace()
|
||||
port: 443
|
||||
---
|
||||
apiVersion: apiregistration.k8s.io/v1
|
||||
kind: APIService
|
||||
metadata:
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("v1alpha1.identity.concierge")
|
||||
labels: #@ labels()
|
||||
spec:
|
||||
version: v1alpha1
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("identity.concierge")
|
||||
groupPriorityMinimum: 9900
|
||||
versionPriority: 15
|
||||
#! caBundle: Do not include this key here. Starts out null, will be updated/owned by the golang code.
|
||||
service:
|
||||
name: #@ defaultResourceNameWithSuffix("api")
|
||||
namespace: #@ namespace()
|
||||
port: 443
|
||||
---
|
||||
apiVersion: #@ pinnipedDevAPIGroupWithPrefix("config.concierge") + "/v1alpha1"
|
||||
kind: CredentialIssuer
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("config")
|
||||
labels: #@ labels()
|
||||
spec:
|
||||
impersonationProxy:
|
||||
mode: #@ data.values.impersonation_proxy_spec.mode
|
||||
#@ if data.values.impersonation_proxy_spec.external_endpoint:
|
||||
externalEndpoint: #@ data.values.impersonation_proxy_spec.external_endpoint
|
||||
#@ end
|
||||
service:
|
||||
type: #@ data.values.impersonation_proxy_spec.service.type
|
||||
#@ if data.values.impersonation_proxy_spec.service.load_balancer_ip:
|
||||
loadBalancerIP: #@ data.values.impersonation_proxy_spec.service.load_balancer_ip
|
||||
#@ end
|
||||
annotations: #@ data.values.impersonation_proxy_spec.service.annotations
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
annotations:
|
||||
#! wait until the SA exists to create this secret so that the token controller does not delete it
|
||||
#! we have this secret at the end so that kubectl will create the service account first
|
||||
kapp.k14s.io/change-rule: "upsert after upserting impersonation-proxy.concierge.pinniped.dev/serviceaccount"
|
||||
kubernetes.io/service-account.name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||
type: kubernetes.io/service-account-token
|
47
deploy_carvel/concierge/config/helpers.lib.yaml
Normal file
47
deploy_carvel/concierge/config/helpers.lib.yaml
Normal file
@ -0,0 +1,47 @@
|
||||
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
#@ load("@ytt:template", "template")
|
||||
|
||||
#@ def defaultResourceName():
|
||||
#@ return data.values.app_name
|
||||
#@ end
|
||||
|
||||
#@ def defaultResourceNameWithSuffix(suffix):
|
||||
#@ return data.values.app_name + "-" + suffix
|
||||
#@ end
|
||||
|
||||
#@ def pinnipedDevAPIGroupWithPrefix(prefix):
|
||||
#@ return prefix + "." + data.values.api_group_suffix
|
||||
#@ end
|
||||
|
||||
#@ def namespace():
|
||||
#@ if data.values.into_namespace:
|
||||
#@ return data.values.into_namespace
|
||||
#@ else:
|
||||
#@ return data.values.namespace
|
||||
#@ end
|
||||
#@ end
|
||||
|
||||
#@ def defaultLabel():
|
||||
#! Note that the name of this label's key is also assumed by kubecertagent.go and impersonator_config.go
|
||||
app: #@ data.values.app_name
|
||||
#@ end
|
||||
|
||||
#@ def deploymentPodLabel():
|
||||
deployment.pinniped.dev: concierge
|
||||
#@ end
|
||||
|
||||
#@ def labels():
|
||||
_: #@ template.replace(defaultLabel())
|
||||
_: #@ template.replace(data.values.custom_labels)
|
||||
#@ end
|
||||
|
||||
#@ def getAndValidateLogLevel():
|
||||
#@ log_level = data.values.log_level
|
||||
#@ if log_level != "info" and log_level != "debug" and log_level != "trace" and log_level != "all":
|
||||
#@ fail("log_level '" + log_level + "' is invalid")
|
||||
#@ end
|
||||
#@ return log_level
|
||||
#@ end
|
296
deploy_carvel/concierge/config/rbac.yaml
Normal file
296
deploy_carvel/concierge/config/rbac.yaml
Normal file
@ -0,0 +1,296 @@
|
||||
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
#@ load("helpers.lib.yaml", "labels", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "pinnipedDevAPIGroupWithPrefix")
|
||||
|
||||
#! Give permission to various cluster-scoped objects
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||
labels: #@ labels()
|
||||
rules:
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ namespaces ]
|
||||
verbs: [ get, list, watch ]
|
||||
- apiGroups: [ apiregistration.k8s.io ]
|
||||
resources: [ apiservices ]
|
||||
verbs: [ get, list, patch, update, watch ]
|
||||
- apiGroups: [ admissionregistration.k8s.io ]
|
||||
resources: [ validatingwebhookconfigurations, mutatingwebhookconfigurations ]
|
||||
verbs: [ get, list, watch ]
|
||||
- apiGroups: [ flowcontrol.apiserver.k8s.io ]
|
||||
resources: [ flowschemas, prioritylevelconfigurations ]
|
||||
verbs: [ get, list, watch ]
|
||||
- apiGroups: [ security.openshift.io ]
|
||||
resources: [ securitycontextconstraints ]
|
||||
verbs: [ use ]
|
||||
resourceNames: [ nonroot ]
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ nodes ]
|
||||
verbs: [ list ]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("config.concierge")
|
||||
resources: [ credentialissuers ]
|
||||
verbs: [ get, list, watch, create ]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("config.concierge")
|
||||
resources: [ credentialissuers/status ]
|
||||
verbs: [ get, patch, update ]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("authentication.concierge")
|
||||
resources: [ jwtauthenticators, webhookauthenticators ]
|
||||
verbs: [ get, list, watch ]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give minimal permissions to impersonation proxy service account
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||
labels: #@ labels()
|
||||
rules:
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ "users", "groups", "serviceaccounts" ]
|
||||
verbs: [ "impersonate" ]
|
||||
- apiGroups: [ "authentication.k8s.io" ]
|
||||
resources: [ "*" ] #! What we really want is userextras/* but the RBAC authorizer only supports */subresource, not resource/*
|
||||
verbs: [ "impersonate" ]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: #@ defaultResourceNameWithSuffix("impersonation-proxy")
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give permission to the kube-cert-agent Pod to run privileged.
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
rules:
|
||||
- apiGroups: [ policy ]
|
||||
resources: [ podsecuritypolicies ]
|
||||
verbs: [ use ]
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: #@ defaultResourceNameWithSuffix("kube-cert-agent")
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give permission to various objects within the app's own namespace
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
rules:
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ services ]
|
||||
verbs: [ create, get, list, patch, update, watch, delete ]
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ secrets ]
|
||||
verbs: [ create, get, list, patch, update, watch, delete ]
|
||||
#! We need to be able to watch pods in our namespace so we can find the kube-cert-agent pods.
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ pods ]
|
||||
verbs: [ get, list, watch ]
|
||||
#! We need to be able to exec into pods in our namespace so we can grab the API server's private key
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ pods/exec ]
|
||||
verbs: [ create ]
|
||||
#! We need to be able to delete pods in our namespace so we can clean up legacy kube-cert-agent pods.
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ pods ]
|
||||
verbs: [ delete ]
|
||||
#! We need to be able to create and update deployments in our namespace so we can manage the kube-cert-agent Deployment.
|
||||
- apiGroups: [ apps ]
|
||||
resources: [ deployments ]
|
||||
verbs: [ create, get, list, patch, update, watch, delete ]
|
||||
#! We need to be able to get replicasets so we can form the correct owner references on our generated objects.
|
||||
- apiGroups: [ apps ]
|
||||
resources: [ replicasets ]
|
||||
verbs: [ get ]
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ configmaps ]
|
||||
verbs: [ list, get, watch ]
|
||||
- apiGroups: [ coordination.k8s.io ]
|
||||
resources: [ leases ]
|
||||
verbs: [ create, get, update ]
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give permission to read pods in the kube-system namespace so we can find the API server's private key
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("kube-system-pod-read")
|
||||
namespace: kube-system
|
||||
labels: #@ labels()
|
||||
rules:
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ pods ]
|
||||
verbs: [ get, list, watch ]
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("kube-system-pod-read")
|
||||
namespace: kube-system
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: #@ defaultResourceNameWithSuffix("kube-system-pod-read")
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Allow both authenticated and unauthenticated TokenCredentialRequests (i.e. allow all requests)
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("pre-authn-apis")
|
||||
labels: #@ labels()
|
||||
rules:
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("login.concierge")
|
||||
resources: [ tokencredentialrequests ]
|
||||
verbs: [ create, list ]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("identity.concierge")
|
||||
resources: [ whoamirequests ]
|
||||
verbs: [ create, list ]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("pre-authn-apis")
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: Group
|
||||
name: system:authenticated
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
- kind: Group
|
||||
name: system:unauthenticated
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: #@ defaultResourceNameWithSuffix("pre-authn-apis")
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give permissions for subjectaccessreviews, tokenreview that is needed by aggregated api servers
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceName()
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: system:auth-delegator
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give permissions for a special configmap of CA bundles that is needed by aggregated api servers
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("extension-apiserver-authentication-reader")
|
||||
namespace: kube-system
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: extension-apiserver-authentication-reader
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give permission to list and watch ConfigMaps in kube-public
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("cluster-info-lister-watcher")
|
||||
namespace: kube-public
|
||||
labels: #@ labels()
|
||||
rules:
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ configmaps ]
|
||||
verbs: [ list, watch ]
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("cluster-info-lister-watcher")
|
||||
namespace: kube-public
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: #@ defaultResourceNameWithSuffix("cluster-info-lister-watcher")
|
||||
apiGroup: rbac.authorization.k8s.io
|
123
deploy_carvel/concierge/config/values.yaml
Normal file
123
deploy_carvel/concierge/config/values.yaml
Normal file
@ -0,0 +1,123 @@
|
||||
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@data/values-schema
|
||||
---
|
||||
#@schema/desc "Namespace of pinniped-concierge"
|
||||
app_name: pinniped-concierge
|
||||
|
||||
#@schema/desc "Creates a new namespace statically in yaml with the given name and installs the app into that namespace."
|
||||
namespace: pinniped-concierge
|
||||
#! If specified, assumes that a namespace of the given name already exists and installs the app into that namespace.
|
||||
#! If both `namespace` and `into_namespace` are specified, then only `into_namespace` is used.
|
||||
#@schema/desc "Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???"
|
||||
#@schema/nullable
|
||||
into_namespace: my-preexisting-namespace
|
||||
|
||||
#! All resources created statically by yaml at install-time and all resources created dynamically
|
||||
#! by controllers at runtime will be labelled with `app: $app_name` and also with the labels
|
||||
#! specified here. The value of `custom_labels` must be a map of string keys to string values.
|
||||
#! The app can be uninstalled either by:
|
||||
#! 1. Deleting the static install-time yaml resources including the static namespace, which will cascade and also delete
|
||||
#! resources that were dynamically created by controllers at runtime
|
||||
#! 2. Or, deleting all resources by label, which does not assume that there was a static install-time yaml namespace.
|
||||
#@schema/desc "All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here."
|
||||
custom_labels: {} #! e.g. {myCustomLabelName: myCustomLabelValue, otherCustomLabelName: otherCustomLabelValue}
|
||||
|
||||
#! Specify how many replicas of the Pinniped server to run.
|
||||
replicas: 2
|
||||
|
||||
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||
image_repo: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||
#@schema/nullable
|
||||
image_digest: sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8
|
||||
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||
image_tag: latest
|
||||
|
||||
#! TODO: preserve even if this file is revised!
|
||||
#@schema/nullable
|
||||
package_image_repo: docker.io/benjaminapetersen/some-pinniped-concierge-package
|
||||
#@schema/nullable
|
||||
package_image_digest: sha256:123456
|
||||
#@schema/nullable
|
||||
package_image_tag: latest
|
||||
#! prob should not be nullable
|
||||
#@schema/nullable
|
||||
package_version: 1.2.3
|
||||
|
||||
#@schema/desc 'Optionally specify a different image for the "kube-cert-agent" pod which is scheduled on the control plane. This image needs only to include `sleep` and `cat` binaries. By default, the same image specified for image_repo/image_digest/image_tag will be re-used.'
|
||||
kube_cert_agent_image: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
|
||||
#! Specifies a secret to be used when pulling the above `image_repo` container image.
|
||||
#! Can be used when the above image_repo is a private registry.
|
||||
#! Typically the value would be the output of: kubectl create secret docker-registry x --docker-server=https://example.io --docker-username="USERNAME" --docker-password="PASSWORD" --dry-run=client -o json | jq -r '.data[".dockerconfigjson"]'
|
||||
#! Optional.
|
||||
#@schema/desc "Specifies a secret to be used when pulling the above `image_repo` container image. Can be used when the image_repo is a private registry."
|
||||
#@schema/nullable
|
||||
image_pull_dockerconfigjson: {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}
|
||||
|
||||
#! Optional.
|
||||
#@schema/desc "Pinniped will try to guess the right K8s API URL for sharing that information with potential clients. This setting allows the guess to be overridden."
|
||||
#@schema/nullable
|
||||
discovery_url: https://example.com
|
||||
|
||||
#@schema/desc "Specify the duration and renewal interval for the API serving certificate. The defaults are set to expire the cert about every 30 days, and to rotate it about every 25 days."
|
||||
api_serving_certificate_duration_seconds: 2592000
|
||||
api_serving_certificate_renew_before_seconds: 2160000
|
||||
|
||||
#@schema/desc 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||
#@schema/nullable
|
||||
log_level: info #! By default, when this value is left unset, only warnings and errors are printed. There is no way to suppress warning and error logs.
|
||||
#@schema/desc "Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json."
|
||||
#@schema/nullable
|
||||
deprecated_log_format: json
|
||||
|
||||
#@schema/desc "run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice"
|
||||
run_as_user: 65532
|
||||
#@schema/desc "run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice"
|
||||
run_as_group: 65532
|
||||
|
||||
#@schema/desc "Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc."
|
||||
api_group_suffix: pinniped.dev
|
||||
|
||||
|
||||
|
||||
#@schema/desc "Customize CredentialIssuer.spec.impersonationProxy to change how the concierge handles impersonation."
|
||||
impersonation_proxy_spec:
|
||||
#! options are "auto", "disabled" or "enabled".
|
||||
#! If auto, the impersonation proxy will run only if the cluster signing key is not available
|
||||
#! and the other strategy does not work.
|
||||
#! If disabled, the impersonation proxy will never run, which could mean that the concierge
|
||||
#! doesn't work at all.
|
||||
#! If enabled, the impersonation proxy will always run regardless of other strategies available.
|
||||
#@schema/desc 'options are "auto", "disabled" or "enabled".'
|
||||
mode: auto
|
||||
#! The endpoint which the client should use to connect to the impersonation proxy.
|
||||
#! If left unset, the client will default to connecting based on the ClusterIP or LoadBalancer
|
||||
#! endpoint.
|
||||
#@schema/desc "The endpoint which the client should use to connect to the impersonation proxy."
|
||||
external_endpoint: http://example.com
|
||||
service:
|
||||
#! Options are "LoadBalancer", "ClusterIP" and "None".
|
||||
#! LoadBalancer automatically provisions a Service of type LoadBalancer pointing at
|
||||
#! the impersonation proxy. Some cloud providers will allocate
|
||||
#! a public IP address by default even on private clusters.
|
||||
#! ClusterIP automatically provisions a Service of type ClusterIP pointing at the
|
||||
#! impersonation proxy.
|
||||
#! None does not provision either and assumes that you have set the external_endpoint
|
||||
#! and set up your own ingress to connect to the impersonation proxy.
|
||||
#@schema/desc 'Options are "LoadBalancer", "ClusterIP" and "None".'
|
||||
type: LoadBalancer
|
||||
#@schema/desc "The annotations that should be set on the ClusterIP or LoadBalancer Service."
|
||||
annotations:
|
||||
{service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "4000"}
|
||||
#@schema/desc "When mode LoadBalancer is set, this will set the LoadBalancer Service's Spec.LoadBalancerIP."
|
||||
load_balancer_ip: 1.2.3.4
|
||||
|
||||
#! Optional.
|
||||
#@schema/desc "Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Concierge containers. These will be used when the Concierge makes backend-to-backend calls to authenticators using HTTPS, e.g. when the Concierge fetches discovery documents, JWKS keys, and POSTs to token webhooks. The Concierge never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY."
|
||||
#@schema/nullable
|
||||
https_proxy: http://proxy.example.com
|
||||
#@schema/desc "NO_PROXY environment variable. do not proxy Kubernetes endpoints"
|
||||
no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local"
|
33
deploy_carvel/concierge/config/z0_crd_overlay.yaml
Normal file
33
deploy_carvel/concierge/config/z0_crd_overlay.yaml
Normal file
@ -0,0 +1,33 @@
|
||||
#! Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:overlay", "overlay")
|
||||
#@ load("helpers.lib.yaml", "labels", "pinnipedDevAPIGroupWithPrefix")
|
||||
#@ load("@ytt:data", "data")
|
||||
|
||||
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"credentialissuers.config.concierge.pinniped.dev"}}), expects=1
|
||||
---
|
||||
metadata:
|
||||
#@overlay/match missing_ok=True
|
||||
labels: #@ labels()
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("credentialissuers.config.concierge")
|
||||
spec:
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("config.concierge")
|
||||
|
||||
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"webhookauthenticators.authentication.concierge.pinniped.dev"}}), expects=1
|
||||
---
|
||||
metadata:
|
||||
#@overlay/match missing_ok=True
|
||||
labels: #@ labels()
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("webhookauthenticators.authentication.concierge")
|
||||
spec:
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("authentication.concierge")
|
||||
|
||||
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"jwtauthenticators.authentication.concierge.pinniped.dev"}}), expects=1
|
||||
---
|
||||
metadata:
|
||||
#@overlay/match missing_ok=True
|
||||
labels: #@ labels()
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("jwtauthenticators.authentication.concierge")
|
||||
spec:
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("authentication.concierge")
|
13
deploy_carvel/concierge/metadata.yml
Normal file
13
deploy_carvel/concierge/metadata.yml
Normal file
@ -0,0 +1,13 @@
|
||||
#@ load("@ytt:data", "data") # for reading data values (generated via ytt's data-values-schema-inspect mode).
|
||||
#@ load("@ytt:yaml", "yaml") # for dynamically decoding the output of ytt's data-values-schema-inspect
|
||||
---
|
||||
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||
kind: PackageMetadata
|
||||
metadata:
|
||||
name: concierge.pinniped.dev
|
||||
spec:
|
||||
displayName: "Pinniped Concierge"
|
||||
longDescription: "Pinniped concierge enables consistent login across Kubernetes clusters on public cloud providers such as AKS, EKS and GKE"
|
||||
shortDescription: "Pinniped concierge enables consistent login across public clouds"
|
||||
categories:
|
||||
- auth
|
30
deploy_carvel/concierge/package-template.yml
Normal file
30
deploy_carvel/concierge/package-template.yml
Normal file
@ -0,0 +1,30 @@
|
||||
#@ load("@ytt:data", "data") # for reading data values (generated via ytt's data-values-schema-inspect mode).
|
||||
#@ load("@ytt:yaml", "yaml") # for dynamically decoding the output of ytt's data-values-schema-inspect
|
||||
---
|
||||
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||
kind: Package
|
||||
metadata:
|
||||
name: #@ "concierge.pinniped.dev." + data.values.package_version
|
||||
spec:
|
||||
refName: concierge.pinniped.dev
|
||||
version: #@ data.values.package_version
|
||||
releaseNotes: |
|
||||
Initial release of the pinniped concierge package, TODO: AUTOMATE THIS??
|
||||
valuesSchema:
|
||||
openAPIv3: #@ yaml.decode(data.values.openapi)["components"]["schemas"]["dataValues"]
|
||||
template:
|
||||
spec:
|
||||
fetch:
|
||||
- imgpkgBundle:
|
||||
#! image: #@ data.values.package_image_repo + "/packages/:" + data.values.package_version
|
||||
image: #@ data.values.package_image_repo
|
||||
template:
|
||||
- ytt:
|
||||
paths:
|
||||
- "config/"
|
||||
- kbld:
|
||||
paths:
|
||||
- ".imgpkg/images.yml"
|
||||
- "-"
|
||||
deploy:
|
||||
- kapp: {}
|
164
deploy_carvel/concierge/schema-openapi.yml
Normal file
164
deploy_carvel/concierge/schema-openapi.yml
Normal file
@ -0,0 +1,164 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
version: 0.1.0
|
||||
title: Schema for data values, generated by ytt
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
dataValues:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
app_name:
|
||||
type: string
|
||||
description: Namespace of pinniped-concierge
|
||||
default: pinniped-concierge
|
||||
namespace:
|
||||
type: string
|
||||
description: Creates a new namespace statically in yaml with the given name and installs the app into that namespace.
|
||||
default: pinniped-concierge
|
||||
into_namespace:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???'
|
||||
default: null
|
||||
custom_labels:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: 'All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here.'
|
||||
properties: {}
|
||||
replicas:
|
||||
type: integer
|
||||
default: 2
|
||||
image_repo:
|
||||
type: string
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
image_digest:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: null
|
||||
image_tag:
|
||||
type: string
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: latest
|
||||
package_image_repo:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_image_digest:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_image_tag:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_version:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
kube_cert_agent_image:
|
||||
type: string
|
||||
description: Optionally specify a different image for the "kube-cert-agent" pod which is scheduled on the control plane. This image needs only to include `sleep` and `cat` binaries. By default, the same image specified for image_repo/image_digest/image_tag will be re-used.
|
||||
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
image_pull_dockerconfigjson:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
nullable: true
|
||||
description: Specifies a secret to be used when pulling the above `image_repo` container image. Can be used when the image_repo is a private registry.
|
||||
properties:
|
||||
auths:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
https://registry.example.com:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
default: USERNAME
|
||||
password:
|
||||
type: string
|
||||
default: PASSWORD
|
||||
auth:
|
||||
type: string
|
||||
default: BASE64_ENCODED_USERNAME_COLON_PASSWORD
|
||||
discovery_url:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Pinniped will try to guess the right K8s API URL for sharing that information with potential clients. This setting allows the guess to be overridden.
|
||||
default: null
|
||||
api_serving_certificate_duration_seconds:
|
||||
type: integer
|
||||
description: Specify the duration and renewal interval for the API serving certificate. The defaults are set to expire the cert about every 30 days, and to rotate it about every 25 days.
|
||||
default: 2592000
|
||||
api_serving_certificate_renew_before_seconds:
|
||||
type: integer
|
||||
default: 2160000
|
||||
log_level:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||
default: null
|
||||
deprecated_log_format:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json.'
|
||||
default: null
|
||||
run_as_user:
|
||||
type: integer
|
||||
description: run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
default: 65532
|
||||
run_as_group:
|
||||
type: integer
|
||||
description: run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
default: 65532
|
||||
api_group_suffix:
|
||||
type: string
|
||||
description: Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
|
||||
default: pinniped.dev
|
||||
impersonation_proxy_spec:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: Customize CredentialIssuer.spec.impersonationProxy to change how the concierge handles impersonation.
|
||||
properties:
|
||||
mode:
|
||||
type: string
|
||||
description: options are "auto", "disabled" or "enabled".
|
||||
default: auto
|
||||
external_endpoint:
|
||||
type: string
|
||||
description: The endpoint which the client should use to connect to the impersonation proxy.
|
||||
default: http://example.com
|
||||
service:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
description: Options are "LoadBalancer", "ClusterIP" and "None".
|
||||
default: LoadBalancer
|
||||
annotations:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: The annotations that should be set on the ClusterIP or LoadBalancer Service.
|
||||
properties:
|
||||
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout:
|
||||
type: string
|
||||
default: "4000"
|
||||
load_balancer_ip:
|
||||
type: string
|
||||
description: When mode LoadBalancer is set, this will set the LoadBalancer Service's Spec.LoadBalancerIP.
|
||||
default: 1.2.3.4
|
||||
https_proxy:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Concierge containers. These will be used when the Concierge makes backend-to-backend calls to authenticators using HTTPS, e.g. when the Concierge fetches discovery documents, JWKS keys, and POSTs to token webhooks. The Concierge never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY.
|
||||
default: null
|
||||
no_proxy:
|
||||
type: string
|
||||
description: NO_PROXY environment variable. do not proxy Kubernetes endpoints
|
||||
default: $(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local
|
62
deploy_carvel/delete.sh
Executable file
62
deploy_carvel/delete.sh
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425
|
||||
set -e # immediately exit
|
||||
set -u # error if variables undefined
|
||||
set -o pipefail # prevent masking errors in a pipeline
|
||||
# set -x # print all executed commands to terminal
|
||||
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
DEFAULT='\033[0m'
|
||||
|
||||
echo_yellow() {
|
||||
echo -e "${YELLOW}>> $@${DEFAULT}\n"
|
||||
# printf "${GREEN}$@${DEFAULT}"
|
||||
}
|
||||
|
||||
echo_green() {
|
||||
echo -e "${GREEN}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
echo_red() {
|
||||
echo -e "${RED}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
echo_blue() {
|
||||
echo -e "${BLUE}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
|
||||
echo_yellow "creating fresh kind cluster - my-pinniped-package-repo-cluster"
|
||||
kind delete cluster --name my-pinniped-package-repo-cluster
|
||||
kind create cluster --name my-pinniped-package-repo-cluster
|
||||
|
||||
#
|
||||
#
|
||||
#echo_yellow "check before install..."
|
||||
#echo_yellow "kubectl get pkgr -A && kubectl get pkg -A && kubectl get pkgi -A"
|
||||
#kubectl get pkgr -A && kubectl get pkg -A && kubectl get pkgi -A
|
||||
## NAMESPACE NAME AGE DESCRIPTION
|
||||
## default pinniped-package-repository 18h Reconcile succeeded
|
||||
## NAMESPACE NAME PACKAGEMETADATA NAME VERSION AGE
|
||||
## default concierge.pinniped.dev.0.25.0 concierge.pinniped.dev 0.25.0 18h16m28s
|
||||
## default supervisor.pinniped.dev.0.25.0 supervisor.pinniped.dev 0.25.0 18h16m28s
|
||||
## NAMESPACE NAME PACKAGE NAME PACKAGE VERSION DESCRIPTION AGE
|
||||
## default supervisor-package-install supervisor.pinniped.dev 0.25.0 Delete failed: Error (see .status.usefulErrorMessage for details) 92m
|
||||
## supervisor-ns supervisor-package-install supervisor.pinniped.dev Reconcile failed: Package supervisor.pinniped.dev not found 18h
|
||||
#
|
||||
#
|
||||
#kubectl delete pkgr pinniped-package-repository
|
||||
## should be automatic
|
||||
## kubectl delete pkg concierge.pinniped.dev.0.25.0
|
||||
## kubectl delete pkg supervisor.pinniped.dev.0.25.0
|
||||
#kubectl delete pkgi supervisor-package-install
|
||||
#kubectl delete pkgi concierge-package-install
|
||||
#
|
||||
#echo_yellow "check after install..."
|
||||
#echo_yellow "kubectl get pkgr -A && kubectl get pkg -A && kubectl get pkgi -A"
|
||||
#kubectl get pkgr -A && kubectl get pkg -A && kubectl get pkgi -A
|
104
deploy_carvel/deploy_supervisor.sh
Executable file
104
deploy_carvel/deploy_supervisor.sh
Executable file
@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425
|
||||
set -e # immediately exit
|
||||
set -u # error if variables undefined
|
||||
set -o pipefail # prevent masking errors in a pipeline
|
||||
# set -x # print all executed commands to terminal
|
||||
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
DEFAULT='\033[0m'
|
||||
|
||||
echo_yellow() {
|
||||
echo -e "${YELLOW}>> $@${DEFAULT}\n"
|
||||
# printf "${GREEN}$@${DEFAULT}"
|
||||
}
|
||||
|
||||
echo_green() {
|
||||
echo -e "${GREEN}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
echo_red() {
|
||||
echo -e "${RED}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
echo_blue() {
|
||||
echo -e "${BLUE}>> $@${DEFAULT}\n"
|
||||
# printf "${BLUE}$@${DEFAULT}"
|
||||
}
|
||||
|
||||
# borrowed from /tmp/integration-test-env
|
||||
# TODO: make new scripts work with the old script?
|
||||
# or how to ensure we can install both
|
||||
# - the old way, ytt or plain yamls
|
||||
# - the new way, with the PackageRepository and Packages
|
||||
# export PINNIPED_TEST_SUPERVISOR_NAMESPACE=supervisor
|
||||
PINNIPED_TEST_SUPERVISOR_NAMESPACE=default
|
||||
# export PINNIPED_TEST_PROXY=http://127.0.0.1:12346
|
||||
PINNIPED_TEST_PROXY=http://127.0.0.1:12346
|
||||
|
||||
# from here forward borrowed from ${repo_root}/hack/prepare-supervisor-on-kind.sh
|
||||
|
||||
# NOPE! Not running this script, so we have to pull the env vars ourselves
|
||||
# however, we can run it against another kind cluster and take a look at it to make sure
|
||||
# we understand what the contents are
|
||||
# Read the env vars output by hack/prepare-for-integration-tests.sh
|
||||
# source /tmp/integration-test-env
|
||||
|
||||
# Choose some filenames.
|
||||
root_ca_crt_path=root_ca.crt
|
||||
root_ca_key_path=root_ca.key
|
||||
tls_crt_path=tls.crt
|
||||
tls_key_path=tls.key
|
||||
|
||||
# Choose an audience name for the Concierge.
|
||||
audience="my-workload-cluster-$(openssl rand -hex 4)"
|
||||
|
||||
# These settings align with how the Dex redirect URI is configured by hack/prepare-for-integration-tests.sh.
|
||||
# Note that this hostname can only be resolved inside the cluster, so we will use a web proxy running inside
|
||||
# the cluster whenever we want to be able to connect to it.
|
||||
issuer_host="pinniped-supervisor-clusterip.supervisor.svc.cluster.local"
|
||||
issuer="https://$issuer_host/some/path"
|
||||
|
||||
|
||||
# Create a CA and TLS serving certificates for the Supervisor.
|
||||
step certificate create \
|
||||
"Supervisor CA" "$root_ca_crt_path" "$root_ca_key_path" \
|
||||
--profile root-ca \
|
||||
--no-password --insecure --force
|
||||
step certificate create \
|
||||
"$issuer_host" "$tls_crt_path" "$tls_key_path" \
|
||||
--profile leaf \
|
||||
--not-after 8760h \
|
||||
--ca "$root_ca_crt_path" --ca-key "$root_ca_key_path" \
|
||||
--no-password --insecure --force
|
||||
|
||||
# Put the TLS certificate into a Secret for the Supervisor.
|
||||
kubectl create secret tls -n "$PINNIPED_TEST_SUPERVISOR_NAMESPACE" my-federation-domain-tls --cert "$tls_crt_path" --key "$tls_key_path" \
|
||||
--dry-run=client --output yaml | kubectl apply -f -
|
||||
|
||||
|
||||
# Make a FederationDomain using the TLS Secret from above.
|
||||
cat <<EOF | kubectl apply --namespace "$PINNIPED_TEST_SUPERVISOR_NAMESPACE" -f -
|
||||
apiVersion: config.supervisor.pinniped.dev/v1alpha1
|
||||
kind: FederationDomain
|
||||
metadata:
|
||||
name: my-federation-domain
|
||||
spec:
|
||||
issuer: $issuer
|
||||
tls:
|
||||
secretName: my-federation-domain-tls
|
||||
EOF
|
||||
|
||||
echo "Waiting for FederationDomain to initialize..."
|
||||
# Sleeping is a race, but that's probably good enough for the purposes of this script.
|
||||
sleep 5
|
||||
|
||||
# Test that the federation domain is working before we proceed.
|
||||
echo "Fetching FederationDomain discovery info..."
|
||||
echo "$PINNIPED_TEST_PROXY - curl -fLsS --cacert $root_ca_crt_path $issuer/.well-known/openid-configuration"
|
||||
https_proxy="$PINNIPED_TEST_PROXY" curl -fLsS --cacert "$root_ca_crt_path" "$issuer/.well-known/openid-configuration" | jq .
|
53
deploy_carvel/noop.sh
Executable file
53
deploy_carvel/noop.sh
Executable file
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#
|
||||
# This script is intended to be used with:
|
||||
# - $repo_root/hack/prepare-for-integration-test.sh --alternate-deploy $(pwd)/deploy_carvel/hack/log-args.sh
|
||||
# and originated with the following:
|
||||
# - https://github.com/jvanzyl/pinniped-charts/blob/main/alternate-deploy-helm
|
||||
# along with this PR to pinniped:
|
||||
# - https://github.com/vmware-tanzu/pinniped/pull/1028
|
||||
set -euo pipefail
|
||||
|
||||
#
|
||||
# Helper functions
|
||||
#
|
||||
function log_note() {
|
||||
GREEN='\033[0;32m'
|
||||
NC='\033[0m'
|
||||
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||
echo -e "${GREEN}$*${NC}"
|
||||
else
|
||||
echo "$*"
|
||||
fi
|
||||
}
|
||||
|
||||
function log_error() {
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||
echo -e "🙁${RED} Error: $* ${NC}"
|
||||
else
|
||||
echo ":( Error: $*"
|
||||
fi
|
||||
}
|
||||
|
||||
function check_dependency() {
|
||||
if ! command -v "$1" >/dev/null; then
|
||||
log_error "Missing dependency..."
|
||||
log_error "$2"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# two vars will be received by this script:
|
||||
# Received: local-user-authenticator
|
||||
# Received: D00A4537-80F1-4AF2-A3B3-5F20BDBB9AEB
|
||||
app=${1}
|
||||
# tag is fed in from the prepare-for-integration-tests.sh script, just uuidgen to identify a
|
||||
# specific docker build of the pinniped-server image.
|
||||
tag=${2}
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
log_note "noop.sh >>> script dir: ${SCRIPT_DIR}"
|
||||
log_note "noop.sh >>> app: ${app} tag: ${tag}"
|
||||
# nothing else, this is a test.
|
18
deploy_carvel/package-repository/.imgpkg/images.yml
Normal file
18
deploy_carvel/package-repository/.imgpkg/images.yml
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
apiVersion: imgpkg.carvel.dev/v1alpha1
|
||||
images:
|
||||
- annotations:
|
||||
kbld.carvel.dev/id: benjaminapetersen/pinniped-package-repo-package-concierge:0.25.0
|
||||
kbld.carvel.dev/origins: |
|
||||
- resolved:
|
||||
tag: 0.25.0
|
||||
url: benjaminapetersen/pinniped-package-repo-package-concierge:0.25.0
|
||||
image: index.docker.io/benjaminapetersen/pinniped-package-repo-package-concierge@sha256:8cfac137dcb7e3edcf0dcc9d032ff67c9d26a7ce863ead5b28bff457336ad3e0
|
||||
- annotations:
|
||||
kbld.carvel.dev/id: benjaminapetersen/pinniped-package-repo-package-supervisor:0.25.0
|
||||
kbld.carvel.dev/origins: |
|
||||
- resolved:
|
||||
tag: 0.25.0
|
||||
url: benjaminapetersen/pinniped-package-repo-package-supervisor:0.25.0
|
||||
image: index.docker.io/benjaminapetersen/pinniped-package-repo-package-supervisor@sha256:f59ad2eb1737f2098e1cd4957f062b0c01de9d1ab7230c58093ab16d2192e302
|
||||
kind: ImagesLock
|
@ -0,0 +1,182 @@
|
||||
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||
kind: Package
|
||||
metadata:
|
||||
name: concierge.pinniped.dev.0.25.0
|
||||
spec:
|
||||
refName: concierge.pinniped.dev
|
||||
version: 0.25.0
|
||||
releaseNotes: |
|
||||
Initial release of the pinniped concierge package, TODO: AUTOMATE THIS??
|
||||
valuesSchema:
|
||||
openAPIv3:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
app_name:
|
||||
type: string
|
||||
description: Namespace of pinniped-concierge
|
||||
default: pinniped-concierge
|
||||
namespace:
|
||||
type: string
|
||||
description: Creates a new namespace statically in yaml with the given name and installs the app into that namespace.
|
||||
default: pinniped-concierge
|
||||
into_namespace:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???'
|
||||
default: null
|
||||
custom_labels:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: 'All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here.'
|
||||
properties: {}
|
||||
replicas:
|
||||
type: integer
|
||||
default: 2
|
||||
image_repo:
|
||||
type: string
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
image_digest:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: null
|
||||
image_tag:
|
||||
type: string
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: latest
|
||||
package_image_repo:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_image_digest:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_image_tag:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_version:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
kube_cert_agent_image:
|
||||
type: string
|
||||
description: Optionally specify a different image for the "kube-cert-agent" pod which is scheduled on the control plane. This image needs only to include `sleep` and `cat` binaries. By default, the same image specified for image_repo/image_digest/image_tag will be re-used.
|
||||
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
image_pull_dockerconfigjson:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
nullable: true
|
||||
description: Specifies a secret to be used when pulling the above `image_repo` container image. Can be used when the image_repo is a private registry.
|
||||
properties:
|
||||
auths:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
https://registry.example.com:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
default: USERNAME
|
||||
password:
|
||||
type: string
|
||||
default: PASSWORD
|
||||
auth:
|
||||
type: string
|
||||
default: BASE64_ENCODED_USERNAME_COLON_PASSWORD
|
||||
discovery_url:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Pinniped will try to guess the right K8s API URL for sharing that information with potential clients. This setting allows the guess to be overridden.
|
||||
default: null
|
||||
api_serving_certificate_duration_seconds:
|
||||
type: integer
|
||||
description: Specify the duration and renewal interval for the API serving certificate. The defaults are set to expire the cert about every 30 days, and to rotate it about every 25 days.
|
||||
default: 2592000
|
||||
api_serving_certificate_renew_before_seconds:
|
||||
type: integer
|
||||
default: 2160000
|
||||
log_level:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||
default: null
|
||||
deprecated_log_format:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json.'
|
||||
default: null
|
||||
run_as_user:
|
||||
type: integer
|
||||
description: run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
default: 65532
|
||||
run_as_group:
|
||||
type: integer
|
||||
description: run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
default: 65532
|
||||
api_group_suffix:
|
||||
type: string
|
||||
description: Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
|
||||
default: pinniped.dev
|
||||
impersonation_proxy_spec:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: Customize CredentialIssuer.spec.impersonationProxy to change how the concierge handles impersonation.
|
||||
properties:
|
||||
mode:
|
||||
type: string
|
||||
description: options are "auto", "disabled" or "enabled".
|
||||
default: auto
|
||||
external_endpoint:
|
||||
type: string
|
||||
description: The endpoint which the client should use to connect to the impersonation proxy.
|
||||
default: http://example.com
|
||||
service:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
description: Options are "LoadBalancer", "ClusterIP" and "None".
|
||||
default: LoadBalancer
|
||||
annotations:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: The annotations that should be set on the ClusterIP or LoadBalancer Service.
|
||||
properties:
|
||||
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout:
|
||||
type: string
|
||||
default: "4000"
|
||||
load_balancer_ip:
|
||||
type: string
|
||||
description: When mode LoadBalancer is set, this will set the LoadBalancer Service's Spec.LoadBalancerIP.
|
||||
default: 1.2.3.4
|
||||
https_proxy:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Concierge containers. These will be used when the Concierge makes backend-to-backend calls to authenticators using HTTPS, e.g. when the Concierge fetches discovery documents, JWKS keys, and POSTs to token webhooks. The Concierge never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY.
|
||||
default: null
|
||||
no_proxy:
|
||||
type: string
|
||||
description: NO_PROXY environment variable. do not proxy Kubernetes endpoints
|
||||
default: $(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local
|
||||
template:
|
||||
spec:
|
||||
fetch:
|
||||
- imgpkgBundle:
|
||||
image: benjaminapetersen/pinniped-package-repo-package-concierge:0.25.0
|
||||
template:
|
||||
- ytt:
|
||||
paths:
|
||||
- config/
|
||||
- kbld:
|
||||
paths:
|
||||
- .imgpkg/images.yml
|
||||
- '-'
|
||||
deploy:
|
||||
- kapp: {}
|
@ -0,0 +1,10 @@
|
||||
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||
kind: PackageMetadata
|
||||
metadata:
|
||||
name: concierge.pinniped.dev
|
||||
spec:
|
||||
displayName: Pinniped Concierge
|
||||
longDescription: Pinniped concierge enables consistent login across Kubernetes clusters on public cloud providers such as AKS, EKS and GKE
|
||||
shortDescription: Pinniped concierge enables consistent login across public clouds
|
||||
categories:
|
||||
- auth
|
@ -0,0 +1,200 @@
|
||||
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||
kind: Package
|
||||
metadata:
|
||||
name: supervisor.pinniped.dev.0.25.0
|
||||
spec:
|
||||
refName: supervisor.pinniped.dev
|
||||
version: 0.25.0
|
||||
releaseNotes: |
|
||||
Initial release of the pinniped supervisor package
|
||||
licenses:
|
||||
- Apache-2.0
|
||||
valuesSchema:
|
||||
openAPIv3:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
app_name:
|
||||
type: string
|
||||
description: Namespace of pinniped-supervisor
|
||||
default: pinniped-supervisor
|
||||
namespace:
|
||||
type: string
|
||||
description: Creates a new namespace statically in yaml with the given name and installs the app into that namespace.
|
||||
default: pinniped-supervisor
|
||||
into_namespace:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???'
|
||||
default: null
|
||||
custom_labels:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: 'All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here.'
|
||||
properties: {}
|
||||
replicas:
|
||||
type: integer
|
||||
description: Specify how many replicas of the Pinniped server to run.
|
||||
default: 2
|
||||
image_repo:
|
||||
type: string
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
image_digest:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: null
|
||||
image_tag:
|
||||
type: string
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: latest
|
||||
package_image_repo:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_image_digest:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_image_tag:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_version:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
image_pull_dockerconfigjson:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
nullable: true
|
||||
properties:
|
||||
auths:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
https://registry.example.com:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
default: USERNAME
|
||||
password:
|
||||
type: string
|
||||
default: PASSWORD
|
||||
auth:
|
||||
type: string
|
||||
default: BASE64_ENCODED_USERNAME_COLON_PASSWORD
|
||||
deprecated_service_http_nodeport_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: will be removed in a future release; when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234
|
||||
default: null
|
||||
deprecated_service_http_nodeport_nodeport:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: will be removed in a future release; the `nodePort` value of the NodePort Service, optional when `deprecated_service_http_nodeport_port` is specified; e.g. 31234
|
||||
default: null
|
||||
deprecated_service_http_loadbalancer_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: will be removed in a future release; when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||
default: null
|
||||
deprecated_service_http_clusterip_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: will be removed in a future release; when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||
default: null
|
||||
service_https_nodeport_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: when specified, creates a NodePort Service with this `port` value, with port 8443 as its `targetPort`; e.g. 31243
|
||||
default: null
|
||||
service_https_nodeport_nodeport:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: the `nodePort` value of the NodePort Service, optional when `service_https_nodeport_port` is specified; e.g. 31243
|
||||
default: null
|
||||
service_https_loadbalancer_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: when specified, creates a LoadBalancer Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||
default: null
|
||||
service_https_clusterip_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: when specified, creates a ClusterIP Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||
default: null
|
||||
service_loadbalancer_ip:
|
||||
type: string
|
||||
nullable: true
|
||||
description: The `loadBalancerIP` value of the LoadBalancer Service. Ignored unless service_https_loadbalancer_port is provided. e.g. 1.2.3.4
|
||||
default: null
|
||||
log_level:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||
default: null
|
||||
deprecated_log_format:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json.'
|
||||
default: null
|
||||
run_as_user:
|
||||
type: integer
|
||||
description: run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
default: 65532
|
||||
run_as_group:
|
||||
type: integer
|
||||
description: run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
default: 65532
|
||||
api_group_suffix:
|
||||
type: string
|
||||
description: Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
|
||||
default: pinniped.dev
|
||||
https_proxy:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Supervisor containers. These will be used when the Supervisor makes backend-to-backend calls to upstream identity providers using HTTPS, e.g. when the Supervisor fetches discovery documents, JWKS keys, and tokens from an upstream OIDC Provider. The Supervisor never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY.
|
||||
default: null
|
||||
no_proxy:
|
||||
type: string
|
||||
description: NO_PROXY environment variable. do not proxy Kubernetes endpoints
|
||||
default: $(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local
|
||||
endpoints:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
nullable: true
|
||||
description: Control the HTTP and HTTPS listeners of the Supervisor.
|
||||
properties:
|
||||
https:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
network:
|
||||
type: string
|
||||
default: tcp | unix | disabled
|
||||
address:
|
||||
type: string
|
||||
default: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix
|
||||
deprecated_insecure_accept_external_unencrypted_http_requests:
|
||||
type: boolean
|
||||
description: Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used.
|
||||
default: false
|
||||
template:
|
||||
spec:
|
||||
fetch:
|
||||
- imgpkgBundle:
|
||||
image: benjaminapetersen/pinniped-package-repo-package-supervisor:0.25.0
|
||||
template:
|
||||
- ytt:
|
||||
paths:
|
||||
- config/
|
||||
- kbld:
|
||||
paths:
|
||||
- .imgpkg/images.yml
|
||||
- '-'
|
||||
deploy:
|
||||
- kapp: {}
|
@ -0,0 +1,10 @@
|
||||
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||
kind: PackageMetadata
|
||||
metadata:
|
||||
name: supervisor.pinniped.dev
|
||||
spec:
|
||||
displayName: Pinniped Supervisor
|
||||
longDescription: Pinniped supervisor allows seamless login across one or many Kubernetes clusters including AKS, EKS and GKE
|
||||
shortDescription: Pinniped supervisor provides login capabilities
|
||||
categories:
|
||||
- auth
|
9
deploy_carvel/packagerepository.0.25.0.yml
Normal file
9
deploy_carvel/packagerepository.0.25.0.yml
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
apiVersion: packaging.carvel.dev/v1alpha1
|
||||
kind: PackageRepository
|
||||
metadata:
|
||||
name: "pinniped-package-repository"
|
||||
spec:
|
||||
fetch:
|
||||
imgpkgBundle:
|
||||
image: "benjaminapetersen/pinniped-package-repo:0.25.0"
|
11
deploy_carvel/supervisor/.imgpkg/images.yml
Normal file
11
deploy_carvel/supervisor/.imgpkg/images.yml
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
apiVersion: imgpkg.carvel.dev/v1alpha1
|
||||
images:
|
||||
- annotations:
|
||||
kbld.carvel.dev/id: projects.registry.vmware.com/pinniped/pinniped-server:latest
|
||||
kbld.carvel.dev/origins: |
|
||||
- resolved:
|
||||
tag: latest
|
||||
url: projects.registry.vmware.com/pinniped/pinniped-server:latest
|
||||
image: projects.registry.vmware.com/pinniped/pinniped-server@sha256:a92183de893eb0b1850cc3a1d33306b96ba2cdb72a8a49c6493a58c01b4fa9cd
|
||||
kind: ImagesLock
|
24
deploy_carvel/supervisor/build.yaml
Normal file
24
deploy_carvel/supervisor/build.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
#@ load("@ytt:data", "data")
|
||||
---
|
||||
apiVersion: kbld.k14s.io/v1alpha1
|
||||
kind: Config
|
||||
minimumRequiredVersion: 0.31.0 #! minimum version of kbld. We probably don't need to specify.
|
||||
overrides:
|
||||
#! TODO: in the pinniped yamls, this is provided by values.yaml, not declared in the deployment.
|
||||
#! we should assess if we want to leave it there or move it to this form of configuration.
|
||||
#! TODO: would also need to make docker.io work???
|
||||
- image: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
newImage: #@ data.values.image_repo
|
||||
|
||||
|
||||
|
||||
|
||||
#! I don't think we need any of these (until we need them 😊). IE, don't use prematurely.
|
||||
#! searchRules: ... # for searching input files to find container images
|
||||
#! overrides: ... # overrides to apply to container images before resolving or building
|
||||
#! sources: ... # source/content of a container image
|
||||
#! destinations: ... # where to push built images
|
||||
#!
|
||||
#!
|
||||
#! source: TODO: we may need this at least to specify that we want kbld to build
|
||||
#! a set of container images that are found in our package config yaml files.
|
3
deploy_carvel/supervisor/config/README.md
Normal file
3
deploy_carvel/supervisor/config/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Pinniped Supervisor Deployment
|
||||
|
||||
See [the how-to guide for details](https://pinniped.dev/docs/howto/install-supervisor/).
|
8
deploy_carvel/supervisor/config/build.yaml
Normal file
8
deploy_carvel/supervisor/config/build.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
apiVersion: kbld.k14s.io/v1alpha1
|
||||
kind: Config
|
||||
sources:
|
||||
- image: docker.io/dkalinin/k8s-simple-app
|
||||
path: .
|
||||
- image: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
path: .
|
@ -0,0 +1,170 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: federationdomains.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
names:
|
||||
categories:
|
||||
- pinniped
|
||||
kind: FederationDomain
|
||||
listKind: FederationDomainList
|
||||
plural: federationdomains
|
||||
singular: federationdomain
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.issuer
|
||||
name: Issuer
|
||||
type: string
|
||||
- jsonPath: .status.status
|
||||
name: Status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: FederationDomain describes the configuration of an OIDC provider.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec of the OIDC provider.
|
||||
properties:
|
||||
issuer:
|
||||
description: "Issuer is the OIDC Provider's issuer, per the OIDC Discovery
|
||||
Metadata document, as well as the identifier that it will use for
|
||||
the iss claim in issued JWTs. This field will also be used as the
|
||||
base URL for any endpoints used by the OIDC Provider (e.g., if your
|
||||
issuer is https://example.com/foo, then your authorization endpoint
|
||||
will look like https://example.com/foo/some/path/to/auth/endpoint).
|
||||
\n See https://openid.net/specs/openid-connect-discovery-1_0.html#rfc.section.3
|
||||
for more information."
|
||||
minLength: 1
|
||||
type: string
|
||||
tls:
|
||||
description: TLS configures how this FederationDomain is served over
|
||||
Transport Layer Security (TLS).
|
||||
properties:
|
||||
secretName:
|
||||
description: "SecretName is an optional name of a Secret in the
|
||||
same namespace, of type `kubernetes.io/tls`, which contains
|
||||
the TLS serving certificate for the HTTPS endpoints served by
|
||||
this FederationDomain. When provided, the TLS Secret named here
|
||||
must contain keys named `tls.crt` and `tls.key` that contain
|
||||
the certificate and private key to use for TLS. \n Server Name
|
||||
Indication (SNI) is an extension to the Transport Layer Security
|
||||
(TLS) supported by all major browsers. \n SecretName is required
|
||||
if you would like to use different TLS certificates for issuers
|
||||
of different hostnames. SNI requests do not include port numbers,
|
||||
so all issuers with the same DNS hostname must use the same
|
||||
SecretName value even if they have different port numbers. \n
|
||||
SecretName is not required when you would like to use only the
|
||||
HTTP endpoints (e.g. when the HTTP listener is configured to
|
||||
listen on loopback interfaces or UNIX domain sockets for traffic
|
||||
from a service mesh sidecar). It is also not required when you
|
||||
would like all requests to this OIDC Provider's HTTPS endpoints
|
||||
to use the default TLS certificate, which is configured elsewhere.
|
||||
\n When your Issuer URL's host is an IP address, then this field
|
||||
is ignored. SNI does not work for IP addresses."
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- issuer
|
||||
type: object
|
||||
status:
|
||||
description: Status of the OIDC provider.
|
||||
properties:
|
||||
lastUpdateTime:
|
||||
description: LastUpdateTime holds the time at which the Status was
|
||||
last updated. It is a pointer to get around some undesirable behavior
|
||||
with respect to the empty metav1.Time value (see https://github.com/kubernetes/kubernetes/issues/86811).
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: Message provides human-readable details about the Status.
|
||||
type: string
|
||||
secrets:
|
||||
description: Secrets contains information about this OIDC Provider's
|
||||
secrets.
|
||||
properties:
|
||||
jwks:
|
||||
description: JWKS holds the name of the corev1.Secret in which
|
||||
this OIDC Provider's signing/verification keys are stored. If
|
||||
it is empty, then the signing/verification keys are either unknown
|
||||
or they don't exist.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
stateEncryptionKey:
|
||||
description: StateSigningKey holds the name of the corev1.Secret
|
||||
in which this OIDC Provider's key for encrypting state parameters
|
||||
is stored.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
stateSigningKey:
|
||||
description: StateSigningKey holds the name of the corev1.Secret
|
||||
in which this OIDC Provider's key for signing state parameters
|
||||
is stored.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
tokenSigningKey:
|
||||
description: TokenSigningKey holds the name of the corev1.Secret
|
||||
in which this OIDC Provider's key for signing tokens is stored.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
status:
|
||||
description: Status holds an enum that describes the state of this
|
||||
OIDC Provider. Note that this Status can represent success or failure.
|
||||
enum:
|
||||
- Success
|
||||
- Duplicate
|
||||
- Invalid
|
||||
- SameIssuerHostMustUseSameSecret
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
@ -0,0 +1,221 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: oidcclients.config.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: config.supervisor.pinniped.dev
|
||||
names:
|
||||
categories:
|
||||
- pinniped
|
||||
kind: OIDCClient
|
||||
listKind: OIDCClientList
|
||||
plural: oidcclients
|
||||
singular: oidcclient
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.allowedScopes[?(@ == "pinniped:request-audience")]
|
||||
name: Privileged Scopes
|
||||
type: string
|
||||
- jsonPath: .status.totalClientSecrets
|
||||
name: Client Secrets
|
||||
type: integer
|
||||
- jsonPath: .status.phase
|
||||
name: Status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: OIDCClient describes the configuration of an OIDC client.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec of the OIDC client.
|
||||
properties:
|
||||
allowedGrantTypes:
|
||||
description: "allowedGrantTypes is a list of the allowed grant_type
|
||||
param values that should be accepted during OIDC flows with this
|
||||
client. \n Must only contain the following values: - authorization_code:
|
||||
allows the client to perform the authorization code grant flow,
|
||||
i.e. allows the webapp to authenticate users. This grant must always
|
||||
be listed. - refresh_token: allows the client to perform refresh
|
||||
grants for the user to extend the user's session. This grant must
|
||||
be listed if allowedScopes lists offline_access. - urn:ietf:params:oauth:grant-type:token-exchange:
|
||||
allows the client to perform RFC8693 token exchange, which is a
|
||||
step in the process to be able to get a cluster credential for the
|
||||
user. This grant must be listed if allowedScopes lists pinniped:request-audience."
|
||||
items:
|
||||
enum:
|
||||
- authorization_code
|
||||
- refresh_token
|
||||
- urn:ietf:params:oauth:grant-type:token-exchange
|
||||
type: string
|
||||
minItems: 1
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
allowedRedirectURIs:
|
||||
description: allowedRedirectURIs is a list of the allowed redirect_uri
|
||||
param values that should be accepted during OIDC flows with this
|
||||
client. Any other uris will be rejected. Must be a URI with the
|
||||
https scheme, unless the hostname is 127.0.0.1 or ::1 which may
|
||||
use the http scheme. Port numbers are not required for 127.0.0.1
|
||||
or ::1 and are ignored when checking for a matching redirect_uri.
|
||||
items:
|
||||
pattern: ^https://.+|^http://(127\.0\.0\.1|\[::1\])(:\d+)?/
|
||||
type: string
|
||||
minItems: 1
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
allowedScopes:
|
||||
description: "allowedScopes is a list of the allowed scopes param
|
||||
values that should be accepted during OIDC flows with this client.
|
||||
\n Must only contain the following values: - openid: The client
|
||||
is allowed to request ID tokens. ID tokens only include the required
|
||||
claims by default (iss, sub, aud, exp, iat). This scope must always
|
||||
be listed. - offline_access: The client is allowed to request an
|
||||
initial refresh token during the authorization code grant flow.
|
||||
This scope must be listed if allowedGrantTypes lists refresh_token.
|
||||
- pinniped:request-audience: The client is allowed to request a
|
||||
new audience value during a RFC8693 token exchange, which is a step
|
||||
in the process to be able to get a cluster credential for the user.
|
||||
openid, username and groups scopes must be listed when this scope
|
||||
is present. This scope must be listed if allowedGrantTypes lists
|
||||
urn:ietf:params:oauth:grant-type:token-exchange. - username: The
|
||||
client is allowed to request that ID tokens contain the user's username.
|
||||
Without the username scope being requested and allowed, the ID token
|
||||
will not contain the user's username. - groups: The client is allowed
|
||||
to request that ID tokens contain the user's group membership, if
|
||||
their group membership is discoverable by the Supervisor. Without
|
||||
the groups scope being requested and allowed, the ID token will
|
||||
not contain groups."
|
||||
items:
|
||||
enum:
|
||||
- openid
|
||||
- offline_access
|
||||
- username
|
||||
- groups
|
||||
- pinniped:request-audience
|
||||
type: string
|
||||
minItems: 1
|
||||
type: array
|
||||
x-kubernetes-list-type: set
|
||||
required:
|
||||
- allowedGrantTypes
|
||||
- allowedRedirectURIs
|
||||
- allowedScopes
|
||||
type: object
|
||||
status:
|
||||
description: Status of the OIDC client.
|
||||
properties:
|
||||
conditions:
|
||||
description: conditions represent the observations of an OIDCClient's
|
||||
current state.
|
||||
items:
|
||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||
type added in Kubernetes 1.19). In a future API version we can
|
||||
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time the condition
|
||||
transitioned from one status to another. This should be when
|
||||
the underlying condition changed. If that is not known, then
|
||||
using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message indicating
|
||||
details about the transition. This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation
|
||||
that the condition was set based upon. For instance, if .metadata.generation
|
||||
is currently 12, but the .status.conditions[x].observedGeneration
|
||||
is 9, the condition is out of date with respect to the current
|
||||
state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier indicating
|
||||
the reason for the condition's last transition. Producers
|
||||
of specific condition types may define expected values and
|
||||
meanings for this field, and whether the values are considered
|
||||
a guaranteed API. The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
--- Many .condition.type values are consistent across resources
|
||||
like Available, but because arbitrary conditions can be useful
|
||||
(see .node.status.conditions), the ability to deconflict is
|
||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
phase:
|
||||
default: Pending
|
||||
description: phase summarizes the overall status of the OIDCClient.
|
||||
enum:
|
||||
- Pending
|
||||
- Ready
|
||||
- Error
|
||||
type: string
|
||||
totalClientSecrets:
|
||||
description: totalClientSecrets is the current number of client secrets
|
||||
that are detected for this OIDCClient.
|
||||
format: int32
|
||||
type: integer
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
236
deploy_carvel/supervisor/config/deployment.yaml
Normal file
236
deploy_carvel/supervisor/config/deployment.yaml
Normal file
@ -0,0 +1,236 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
#@ load("@ytt:yaml", "yaml")
|
||||
#@ load("helpers.lib.yaml",
|
||||
#@ "defaultLabel",
|
||||
#@ "labels",
|
||||
#@ "deploymentPodLabel",
|
||||
#@ "namespace",
|
||||
#@ "defaultResourceName",
|
||||
#@ "defaultResourceNameWithSuffix",
|
||||
#@ "pinnipedDevAPIGroupWithPrefix",
|
||||
#@ "getPinnipedConfigMapData",
|
||||
#@ "hasUnixNetworkEndpoint",
|
||||
#@ )
|
||||
#@ load("@ytt:template", "template")
|
||||
|
||||
#@ if not data.values.into_namespace:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: #@ data.values.namespace
|
||||
labels: #@ labels()
|
||||
#@ end
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("static-config")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
data:
|
||||
#@yaml/text-templated-strings
|
||||
pinniped.yaml: #@ yaml.encode(getPinnipedConfigMapData())
|
||||
---
|
||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: image-pull-secret
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
data:
|
||||
.dockerconfigjson: #@ data.values.image_pull_dockerconfigjson
|
||||
#@ end
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
spec:
|
||||
replicas: #@ data.values.replicas
|
||||
selector:
|
||||
#! In hindsight, this should have been deploymentPodLabel(), but this field is immutable so changing it would break upgrades.
|
||||
matchLabels: #@ defaultLabel()
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
#! This has always included defaultLabel(), which is used by this Deployment's selector.
|
||||
_: #@ template.replace(defaultLabel())
|
||||
#! More recently added the more unique deploymentPodLabel() so Services can select these Pods more specifically
|
||||
#! without accidentally selecting pods from any future Deployments which might also want to use the defaultLabel().
|
||||
_: #@ template.replace(deploymentPodLabel())
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: #@ data.values.run_as_user
|
||||
runAsGroup: #@ data.values.run_as_group
|
||||
serviceAccountName: #@ defaultResourceName()
|
||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||
imagePullSecrets:
|
||||
- name: image-pull-secret
|
||||
#@ end
|
||||
containers:
|
||||
- name: #@ defaultResourceName()
|
||||
#@ if data.values.image_digest:
|
||||
image: #@ data.values.image_repo + "@" + data.values.image_digest
|
||||
#@ else:
|
||||
image: #@ data.values.image_repo + ":" + data.values.image_tag
|
||||
#@ end
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- pinniped-supervisor
|
||||
- /etc/podinfo
|
||||
- /etc/config/pinniped.yaml
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: [ "ALL" ]
|
||||
#! seccompProfile was introduced in Kube v1.19. Using it on an older Kube version will result in a
|
||||
#! kubectl validation error when installing via `kubectl apply`, which can be ignored using kubectl's
|
||||
#! `--validate=false` flag. Note that installing via `kapp` does not complain about this validation error.
|
||||
seccompProfile:
|
||||
type: "RuntimeDefault"
|
||||
resources:
|
||||
requests:
|
||||
#! If OIDCClient CRs are being used, then the Supervisor needs enough CPU to run expensive bcrypt
|
||||
#! operations inside the implementation of the token endpoint for any authcode flows performed by those
|
||||
#! clients, so for that use case administrators may wish to increase the requests.cpu value to more
|
||||
#! closely align with their anticipated needs. Increasing this value will cause Kubernetes to give more
|
||||
#! available CPU to this process during times of high CPU contention. By default, don't ask for too much
|
||||
#! because that would make it impossible to install the Pinniped Supervisor on small clusters.
|
||||
#! Aside from performing bcrypts at the token endpoint for those clients, the Supervisor is not a
|
||||
#! particularly CPU-intensive process.
|
||||
cpu: "100m" #! by default, request one-tenth of a CPU
|
||||
memory: "128Mi"
|
||||
limits:
|
||||
#! By declaring a CPU limit that is not equal to the CPU request value, the Supervisor will be classified
|
||||
#! by Kubernetes to have "burstable" quality of service.
|
||||
#! See https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#create-a-pod-that-gets-assigned-a-qos-class-of-burstable
|
||||
#! If OIDCClient CRs are being used, and lots of simultaneous users have active sessions, then it is hard
|
||||
#! pre-determine what the CPU limit should be for that use case. Guessing too low would cause the
|
||||
#! pod's CPU usage to be throttled, resulting in poor performance. Guessing too high would allow clients
|
||||
#! to cause the usage of lots of CPU resources. Administrators who have a good sense of anticipated usage
|
||||
#! patterns may choose to set the requests.cpu and limits.cpu differently from these defaults.
|
||||
cpu: "1000m" #! by default, throttle each pod's usage at 1 CPU
|
||||
memory: "128Mi"
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /etc/config
|
||||
readOnly: true
|
||||
- name: podinfo
|
||||
mountPath: /etc/podinfo
|
||||
readOnly: true
|
||||
#@ if hasUnixNetworkEndpoint():
|
||||
- name: socket
|
||||
mountPath: /pinniped_socket
|
||||
readOnly: false #! writable to allow for socket use
|
||||
#@ end
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
protocol: TCP
|
||||
env:
|
||||
#@ if data.values.https_proxy:
|
||||
- name: HTTPS_PROXY
|
||||
value: #@ data.values.https_proxy
|
||||
#@ end
|
||||
#@ if data.values.https_proxy and data.values.no_proxy:
|
||||
- name: NO_PROXY
|
||||
value: #@ data.values.no_proxy
|
||||
#@ end
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8443
|
||||
scheme: HTTPS
|
||||
initialDelaySeconds: 2
|
||||
timeoutSeconds: 15
|
||||
periodSeconds: 10
|
||||
failureThreshold: 5
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8443
|
||||
scheme: HTTPS
|
||||
initialDelaySeconds: 2
|
||||
timeoutSeconds: 3
|
||||
periodSeconds: 10
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: #@ defaultResourceNameWithSuffix("static-config")
|
||||
- name: podinfo
|
||||
downwardAPI:
|
||||
items:
|
||||
- path: "labels"
|
||||
fieldRef:
|
||||
fieldPath: metadata.labels
|
||||
- path: "namespace"
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- path: "name"
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
#@ if hasUnixNetworkEndpoint():
|
||||
- name: socket
|
||||
emptyDir: {}
|
||||
#@ end
|
||||
#! This will help make sure our multiple pods run on different nodes, making
|
||||
#! our deployment "more" "HA".
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 50
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels: #@ deploymentPodLabel()
|
||||
topologyKey: kubernetes.io/hostname
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
#! If name is changed, must also change names.apiService in the ConfigMap above and spec.service.name in the APIService below.
|
||||
name: #@ defaultResourceNameWithSuffix("api")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||
annotations:
|
||||
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector: #@ deploymentPodLabel()
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
targetPort: 10250
|
||||
---
|
||||
apiVersion: apiregistration.k8s.io/v1
|
||||
kind: APIService
|
||||
metadata:
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("v1alpha1.clientsecret.supervisor")
|
||||
labels: #@ labels()
|
||||
spec:
|
||||
version: v1alpha1
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("clientsecret.supervisor")
|
||||
groupPriorityMinimum: 9900
|
||||
versionPriority: 15
|
||||
#! caBundle: Do not include this key here. Starts out null, will be updated/owned by the golang code.
|
||||
service:
|
||||
name: #@ defaultResourceNameWithSuffix("api")
|
||||
namespace: #@ namespace()
|
||||
port: 443
|
88
deploy_carvel/supervisor/config/helpers.lib.yaml
Normal file
88
deploy_carvel/supervisor/config/helpers.lib.yaml
Normal file
@ -0,0 +1,88 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
#@ load("@ytt:template", "template")
|
||||
|
||||
#@ def defaultResourceName():
|
||||
#@ return data.values.app_name
|
||||
#@ end
|
||||
|
||||
#@ def defaultResourceNameWithSuffix(suffix):
|
||||
#@ return data.values.app_name + "-" + suffix
|
||||
#@ end
|
||||
|
||||
#@ def pinnipedDevAPIGroupWithPrefix(prefix):
|
||||
#@ return prefix + "." + data.values.api_group_suffix
|
||||
#@ end
|
||||
|
||||
#@ def namespace():
|
||||
#@ if data.values.into_namespace:
|
||||
#@ return data.values.into_namespace
|
||||
#@ else:
|
||||
#@ return data.values.namespace
|
||||
#@ end
|
||||
#@ end
|
||||
|
||||
#@ def defaultLabel():
|
||||
app: #@ data.values.app_name
|
||||
#@ end
|
||||
|
||||
#@ def deploymentPodLabel():
|
||||
deployment.pinniped.dev: supervisor
|
||||
#@ end
|
||||
|
||||
#@ def labels():
|
||||
_: #@ template.replace(defaultLabel())
|
||||
_: #@ template.replace(data.values.custom_labels)
|
||||
#@ end
|
||||
|
||||
#@ def getAndValidateLogLevel():
|
||||
#@ log_level = data.values.log_level
|
||||
#@ if log_level != "info" and log_level != "debug" and log_level != "trace" and log_level != "all":
|
||||
#@ fail("log_level '" + log_level + "' is invalid")
|
||||
#@ end
|
||||
#@ return log_level
|
||||
#@ end
|
||||
|
||||
#@ def getPinnipedConfigMapData():
|
||||
#@ config = {
|
||||
#@ "apiGroupSuffix": data.values.api_group_suffix,
|
||||
#@ "names": {
|
||||
#@ "defaultTLSCertificateSecret": defaultResourceNameWithSuffix("default-tls-certificate"),
|
||||
#@ "apiService": defaultResourceNameWithSuffix("api"),
|
||||
#@ },
|
||||
#@ "labels": labels(),
|
||||
#@ "insecureAcceptExternalUnencryptedHttpRequests": data.values.deprecated_insecure_accept_external_unencrypted_http_requests
|
||||
#@ }
|
||||
#@ if data.values.log_level or data.values.deprecated_log_format:
|
||||
#@ config["log"] = {}
|
||||
#@ end
|
||||
#@ if data.values.log_level:
|
||||
#@ config["log"]["level"] = getAndValidateLogLevel()
|
||||
#@ end
|
||||
#@ if data.values.deprecated_log_format:
|
||||
#@ config["log"]["format"] = data.values.deprecated_log_format
|
||||
#@ end
|
||||
#@ if data.values.endpoints:
|
||||
#@ config["endpoints"] = data.values.endpoints
|
||||
#@ end
|
||||
#@ return config
|
||||
#@ end
|
||||
|
||||
#@ def getattr_safe(val, *args):
|
||||
#@ out = None
|
||||
#@ for arg in args:
|
||||
#@ if not hasattr(val, arg):
|
||||
#@ return None
|
||||
#@ end
|
||||
#@ out = getattr(val, arg)
|
||||
#@ val = out
|
||||
#@ end
|
||||
#@ return out
|
||||
#@ end
|
||||
|
||||
#@ def hasUnixNetworkEndpoint():
|
||||
#@ return getattr_safe(data.values.endpoints, "http", "network") == "unix" or \
|
||||
#@ getattr_safe(data.values.endpoints, "https", "network") == "unix"
|
||||
#@ end
|
@ -0,0 +1,319 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: activedirectoryidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
names:
|
||||
categories:
|
||||
- pinniped
|
||||
- pinniped-idp
|
||||
- pinniped-idps
|
||||
kind: ActiveDirectoryIdentityProvider
|
||||
listKind: ActiveDirectoryIdentityProviderList
|
||||
plural: activedirectoryidentityproviders
|
||||
singular: activedirectoryidentityprovider
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.host
|
||||
name: Host
|
||||
type: string
|
||||
- jsonPath: .status.phase
|
||||
name: Status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: ActiveDirectoryIdentityProvider describes the configuration of
|
||||
an upstream Microsoft Active Directory identity provider.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec for configuring the identity provider.
|
||||
properties:
|
||||
bind:
|
||||
description: Bind contains the configuration for how to provide access
|
||||
credentials during an initial bind to the ActiveDirectory server
|
||||
to be allowed to perform searches and binds to validate a user's
|
||||
credentials during a user's authentication attempt.
|
||||
properties:
|
||||
secretName:
|
||||
description: SecretName contains the name of a namespace-local
|
||||
Secret object that provides the username and password for an
|
||||
Active Directory bind user. This account will be used to perform
|
||||
LDAP searches. The Secret should be of type "kubernetes.io/basic-auth"
|
||||
which includes "username" and "password" keys. The username
|
||||
value should be the full dn (distinguished name) of your bind
|
||||
account, e.g. "cn=bind-account,ou=users,dc=example,dc=com".
|
||||
The password must be non-empty.
|
||||
minLength: 1
|
||||
type: string
|
||||
required:
|
||||
- secretName
|
||||
type: object
|
||||
groupSearch:
|
||||
description: GroupSearch contains the configuration for searching
|
||||
for a user's group membership in ActiveDirectory.
|
||||
properties:
|
||||
attributes:
|
||||
description: Attributes specifies how the group's information
|
||||
should be read from each ActiveDirectory entry which was found
|
||||
as the result of the group search.
|
||||
properties:
|
||||
groupName:
|
||||
description: GroupName specifies the name of the attribute
|
||||
in the Active Directory entries whose value shall become
|
||||
a group name in the user's list of groups after a successful
|
||||
authentication. The value of this field is case-sensitive
|
||||
and must match the case of the attribute name returned by
|
||||
the ActiveDirectory server in the user's entry. E.g. "cn"
|
||||
for common name. Distinguished names can be used by specifying
|
||||
lower-case "dn". Optional. When not specified, this defaults
|
||||
to a custom field that looks like "sAMAccountName@domain",
|
||||
where domain is constructed from the domain components of
|
||||
the group DN.
|
||||
type: string
|
||||
type: object
|
||||
base:
|
||||
description: Base is the dn (distinguished name) that should be
|
||||
used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com".
|
||||
Optional, when not specified it will be based on the result
|
||||
of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
|
||||
The default behavior searches your entire domain for groups.
|
||||
It may make sense to specify a subtree as a search base if you
|
||||
wish to exclude some groups for security reasons or to make
|
||||
searches faster.
|
||||
type: string
|
||||
filter:
|
||||
description: Filter is the ActiveDirectory search filter which
|
||||
should be applied when searching for groups for a user. The
|
||||
pattern "{}" must occur in the filter at least once and will
|
||||
be dynamically replaced by the value of an attribute of the
|
||||
user entry found as a result of the user search. Which attribute's
|
||||
value is used to replace the placeholder(s) depends on the value
|
||||
of UserAttributeForFilter. E.g. "member={}" or "&(objectClass=groupOfNames)(member={})".
|
||||
For more information about ActiveDirectory filters, see https://ldap.com/ldap-filters.
|
||||
Note that the dn (distinguished name) is not an attribute of
|
||||
an entry, so "dn={}" cannot be used. Optional. When not specified,
|
||||
the default will act as if the filter were specified as "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:={})".
|
||||
This searches nested groups by default. Note that nested group
|
||||
search can be slow for some Active Directory servers. To disable
|
||||
it, you can set the filter to "(&(objectClass=group)(member={})"
|
||||
type: string
|
||||
skipGroupRefresh:
|
||||
description: "The user's group membership is refreshed as they
|
||||
interact with the supervisor to obtain new credentials (as their
|
||||
old credentials expire). This allows group membership changes
|
||||
to be quickly reflected into Kubernetes clusters. Since group
|
||||
membership is often used to bind authorization policies, it
|
||||
is important to keep the groups observed in Kubernetes clusters
|
||||
in-sync with the identity provider. \n In some environments,
|
||||
frequent group membership queries may result in a significant
|
||||
performance impact on the identity provider and/or the supervisor.
|
||||
The best approach to handle performance impacts is to tweak
|
||||
the group query to be more performant, for example by disabling
|
||||
nested group search or by using a more targeted group search
|
||||
base. \n If the group search query cannot be made performant
|
||||
and you are willing to have group memberships remain static
|
||||
for approximately a day, then set skipGroupRefresh to true.
|
||||
\ This is an insecure configuration as authorization policies
|
||||
that are bound to group membership will not notice if a user
|
||||
has been removed from a particular group until their next login.
|
||||
\n This is an experimental feature that may be removed or significantly
|
||||
altered in the future. Consumers of this configuration should
|
||||
carefully read all release notes before upgrading to ensure
|
||||
that the meaning of this field has not changed."
|
||||
type: boolean
|
||||
userAttributeForFilter:
|
||||
description: UserAttributeForFilter specifies which attribute's
|
||||
value from the user entry found as a result of the user search
|
||||
will be used to replace the "{}" placeholder(s) in the group
|
||||
search Filter. For example, specifying "uid" as the UserAttributeForFilter
|
||||
while specifying "&(objectClass=posixGroup)(memberUid={})" as
|
||||
the Filter would search for groups by replacing the "{}" placeholder
|
||||
in the Filter with the value of the user's "uid" attribute.
|
||||
Optional. When not specified, the default will act as if "dn"
|
||||
were specified. For example, leaving UserAttributeForFilter
|
||||
unspecified while specifying "&(objectClass=groupOfNames)(member={})"
|
||||
as the Filter would search for groups by replacing the "{}"
|
||||
placeholder(s) with the dn (distinguished name) of the user.
|
||||
type: string
|
||||
type: object
|
||||
host:
|
||||
description: 'Host is the hostname of this Active Directory identity
|
||||
provider, i.e., where to connect. For example: ldap.example.com:636.'
|
||||
minLength: 1
|
||||
type: string
|
||||
tls:
|
||||
description: TLS contains the connection settings for how to establish
|
||||
the connection to the Host.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||
If omitted, a default set of system roots will be trusted.
|
||||
type: string
|
||||
type: object
|
||||
userSearch:
|
||||
description: UserSearch contains the configuration for searching for
|
||||
a user by name in Active Directory.
|
||||
properties:
|
||||
attributes:
|
||||
description: Attributes specifies how the user's information should
|
||||
be read from the ActiveDirectory entry which was found as the
|
||||
result of the user search.
|
||||
properties:
|
||||
uid:
|
||||
description: UID specifies the name of the attribute in the
|
||||
ActiveDirectory entry which whose value shall be used to
|
||||
uniquely identify the user within this ActiveDirectory provider
|
||||
after a successful authentication. Optional, when empty
|
||||
this defaults to "objectGUID".
|
||||
type: string
|
||||
username:
|
||||
description: Username specifies the name of the attribute
|
||||
in Active Directory entry whose value shall become the username
|
||||
of the user after a successful authentication. Optional,
|
||||
when empty this defaults to "userPrincipalName".
|
||||
type: string
|
||||
type: object
|
||||
base:
|
||||
description: Base is the dn (distinguished name) that should be
|
||||
used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
|
||||
Optional, when not specified it will be based on the result
|
||||
of a query for the defaultNamingContext (see https://docs.microsoft.com/en-us/windows/win32/adschema/rootdse).
|
||||
The default behavior searches your entire domain for users.
|
||||
It may make sense to specify a subtree as a search base if you
|
||||
wish to exclude some users or to make searches faster.
|
||||
type: string
|
||||
filter:
|
||||
description: Filter is the search filter which should be applied
|
||||
when searching for users. The pattern "{}" must occur in the
|
||||
filter at least once and will be dynamically replaced by the
|
||||
username for which the search is being run. E.g. "mail={}" or
|
||||
"&(objectClass=person)(uid={})". For more information about
|
||||
LDAP filters, see https://ldap.com/ldap-filters. Note that the
|
||||
dn (distinguished name) is not an attribute of an entry, so
|
||||
"dn={}" cannot be used. Optional. When not specified, the default
|
||||
will be '(&(objectClass=person)(!(objectClass=computer))(!(showInAdvancedViewOnly=TRUE))(|(sAMAccountName={}")(mail={})(userPrincipalName={})(sAMAccountType=805306368))'
|
||||
This means that the user is a person, is not a computer, the
|
||||
sAMAccountType is for a normal user account, and is not shown
|
||||
in advanced view only (which would likely mean its a system
|
||||
created service account with advanced permissions). Also, either
|
||||
the sAMAccountName, the userPrincipalName, or the mail attribute
|
||||
matches the input username.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- host
|
||||
type: object
|
||||
status:
|
||||
description: Status of the identity provider.
|
||||
properties:
|
||||
conditions:
|
||||
description: Represents the observations of an identity provider's
|
||||
current state.
|
||||
items:
|
||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||
type added in Kubernetes 1.19). In a future API version we can
|
||||
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time the condition
|
||||
transitioned from one status to another. This should be when
|
||||
the underlying condition changed. If that is not known, then
|
||||
using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message indicating
|
||||
details about the transition. This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation
|
||||
that the condition was set based upon. For instance, if .metadata.generation
|
||||
is currently 12, but the .status.conditions[x].observedGeneration
|
||||
is 9, the condition is out of date with respect to the current
|
||||
state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier indicating
|
||||
the reason for the condition's last transition. Producers
|
||||
of specific condition types may define expected values and
|
||||
meanings for this field, and whether the values are considered
|
||||
a guaranteed API. The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
--- Many .condition.type values are consistent across resources
|
||||
like Available, but because arbitrary conditions can be useful
|
||||
(see .node.status.conditions), the ability to deconflict is
|
||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
phase:
|
||||
default: Pending
|
||||
description: Phase summarizes the overall status of the ActiveDirectoryIdentityProvider.
|
||||
enum:
|
||||
- Pending
|
||||
- Ready
|
||||
- Error
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
@ -0,0 +1,316 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: ldapidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
names:
|
||||
categories:
|
||||
- pinniped
|
||||
- pinniped-idp
|
||||
- pinniped-idps
|
||||
kind: LDAPIdentityProvider
|
||||
listKind: LDAPIdentityProviderList
|
||||
plural: ldapidentityproviders
|
||||
singular: ldapidentityprovider
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.host
|
||||
name: Host
|
||||
type: string
|
||||
- jsonPath: .status.phase
|
||||
name: Status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: LDAPIdentityProvider describes the configuration of an upstream
|
||||
Lightweight Directory Access Protocol (LDAP) identity provider.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec for configuring the identity provider.
|
||||
properties:
|
||||
bind:
|
||||
description: Bind contains the configuration for how to provide access
|
||||
credentials during an initial bind to the LDAP server to be allowed
|
||||
to perform searches and binds to validate a user's credentials during
|
||||
a user's authentication attempt.
|
||||
properties:
|
||||
secretName:
|
||||
description: SecretName contains the name of a namespace-local
|
||||
Secret object that provides the username and password for an
|
||||
LDAP bind user. This account will be used to perform LDAP searches.
|
||||
The Secret should be of type "kubernetes.io/basic-auth" which
|
||||
includes "username" and "password" keys. The username value
|
||||
should be the full dn (distinguished name) of your bind account,
|
||||
e.g. "cn=bind-account,ou=users,dc=example,dc=com". The password
|
||||
must be non-empty.
|
||||
minLength: 1
|
||||
type: string
|
||||
required:
|
||||
- secretName
|
||||
type: object
|
||||
groupSearch:
|
||||
description: GroupSearch contains the configuration for searching
|
||||
for a user's group membership in the LDAP provider.
|
||||
properties:
|
||||
attributes:
|
||||
description: Attributes specifies how the group's information
|
||||
should be read from each LDAP entry which was found as the result
|
||||
of the group search.
|
||||
properties:
|
||||
groupName:
|
||||
description: GroupName specifies the name of the attribute
|
||||
in the LDAP entries whose value shall become a group name
|
||||
in the user's list of groups after a successful authentication.
|
||||
The value of this field is case-sensitive and must match
|
||||
the case of the attribute name returned by the LDAP server
|
||||
in the user's entry. E.g. "cn" for common name. Distinguished
|
||||
names can be used by specifying lower-case "dn". Optional.
|
||||
When not specified, the default will act as if the GroupName
|
||||
were specified as "dn" (distinguished name).
|
||||
type: string
|
||||
type: object
|
||||
base:
|
||||
description: Base is the dn (distinguished name) that should be
|
||||
used as the search base when searching for groups. E.g. "ou=groups,dc=example,dc=com".
|
||||
When not specified, no group search will be performed and authenticated
|
||||
users will not belong to any groups from the LDAP provider.
|
||||
Also, when not specified, the values of Filter, UserAttributeForFilter,
|
||||
Attributes, and SkipGroupRefresh are ignored.
|
||||
type: string
|
||||
filter:
|
||||
description: Filter is the LDAP search filter which should be
|
||||
applied when searching for groups for a user. The pattern "{}"
|
||||
must occur in the filter at least once and will be dynamically
|
||||
replaced by the value of an attribute of the user entry found
|
||||
as a result of the user search. Which attribute's value is used
|
||||
to replace the placeholder(s) depends on the value of UserAttributeForFilter.
|
||||
For more information about LDAP filters, see https://ldap.com/ldap-filters.
|
||||
Note that the dn (distinguished name) is not an attribute of
|
||||
an entry, so "dn={}" cannot be used. Optional. When not specified,
|
||||
the default will act as if the Filter were specified as "member={}".
|
||||
type: string
|
||||
skipGroupRefresh:
|
||||
description: "The user's group membership is refreshed as they
|
||||
interact with the supervisor to obtain new credentials (as their
|
||||
old credentials expire). This allows group membership changes
|
||||
to be quickly reflected into Kubernetes clusters. Since group
|
||||
membership is often used to bind authorization policies, it
|
||||
is important to keep the groups observed in Kubernetes clusters
|
||||
in-sync with the identity provider. \n In some environments,
|
||||
frequent group membership queries may result in a significant
|
||||
performance impact on the identity provider and/or the supervisor.
|
||||
The best approach to handle performance impacts is to tweak
|
||||
the group query to be more performant, for example by disabling
|
||||
nested group search or by using a more targeted group search
|
||||
base. \n If the group search query cannot be made performant
|
||||
and you are willing to have group memberships remain static
|
||||
for approximately a day, then set skipGroupRefresh to true.
|
||||
\ This is an insecure configuration as authorization policies
|
||||
that are bound to group membership will not notice if a user
|
||||
has been removed from a particular group until their next login.
|
||||
\n This is an experimental feature that may be removed or significantly
|
||||
altered in the future. Consumers of this configuration should
|
||||
carefully read all release notes before upgrading to ensure
|
||||
that the meaning of this field has not changed."
|
||||
type: boolean
|
||||
userAttributeForFilter:
|
||||
description: UserAttributeForFilter specifies which attribute's
|
||||
value from the user entry found as a result of the user search
|
||||
will be used to replace the "{}" placeholder(s) in the group
|
||||
search Filter. For example, specifying "uid" as the UserAttributeForFilter
|
||||
while specifying "&(objectClass=posixGroup)(memberUid={})" as
|
||||
the Filter would search for groups by replacing the "{}" placeholder
|
||||
in the Filter with the value of the user's "uid" attribute.
|
||||
Optional. When not specified, the default will act as if "dn"
|
||||
were specified. For example, leaving UserAttributeForFilter
|
||||
unspecified while specifying "&(objectClass=groupOfNames)(member={})"
|
||||
as the Filter would search for groups by replacing the "{}"
|
||||
placeholder(s) with the dn (distinguished name) of the user.
|
||||
type: string
|
||||
type: object
|
||||
host:
|
||||
description: 'Host is the hostname of this LDAP identity provider,
|
||||
i.e., where to connect. For example: ldap.example.com:636.'
|
||||
minLength: 1
|
||||
type: string
|
||||
tls:
|
||||
description: TLS contains the connection settings for how to establish
|
||||
the connection to the Host.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||
If omitted, a default set of system roots will be trusted.
|
||||
type: string
|
||||
type: object
|
||||
userSearch:
|
||||
description: UserSearch contains the configuration for searching for
|
||||
a user by name in the LDAP provider.
|
||||
properties:
|
||||
attributes:
|
||||
description: Attributes specifies how the user's information should
|
||||
be read from the LDAP entry which was found as the result of
|
||||
the user search.
|
||||
properties:
|
||||
uid:
|
||||
description: UID specifies the name of the attribute in the
|
||||
LDAP entry which whose value shall be used to uniquely identify
|
||||
the user within this LDAP provider after a successful authentication.
|
||||
E.g. "uidNumber" or "objectGUID". The value of this field
|
||||
is case-sensitive and must match the case of the attribute
|
||||
name returned by the LDAP server in the user's entry. Distinguished
|
||||
names can be used by specifying lower-case "dn".
|
||||
minLength: 1
|
||||
type: string
|
||||
username:
|
||||
description: Username specifies the name of the attribute
|
||||
in the LDAP entry whose value shall become the username
|
||||
of the user after a successful authentication. This would
|
||||
typically be the same attribute name used in the user search
|
||||
filter, although it can be different. E.g. "mail" or "uid"
|
||||
or "userPrincipalName". The value of this field is case-sensitive
|
||||
and must match the case of the attribute name returned by
|
||||
the LDAP server in the user's entry. Distinguished names
|
||||
can be used by specifying lower-case "dn". When this field
|
||||
is set to "dn" then the LDAPIdentityProviderUserSearch's
|
||||
Filter field cannot be blank, since the default value of
|
||||
"dn={}" would not work.
|
||||
minLength: 1
|
||||
type: string
|
||||
type: object
|
||||
base:
|
||||
description: Base is the dn (distinguished name) that should be
|
||||
used as the search base when searching for users. E.g. "ou=users,dc=example,dc=com".
|
||||
minLength: 1
|
||||
type: string
|
||||
filter:
|
||||
description: Filter is the LDAP search filter which should be
|
||||
applied when searching for users. The pattern "{}" must occur
|
||||
in the filter at least once and will be dynamically replaced
|
||||
by the username for which the search is being run. E.g. "mail={}"
|
||||
or "&(objectClass=person)(uid={})". For more information about
|
||||
LDAP filters, see https://ldap.com/ldap-filters. Note that the
|
||||
dn (distinguished name) is not an attribute of an entry, so
|
||||
"dn={}" cannot be used. Optional. When not specified, the default
|
||||
will act as if the Filter were specified as the value from Attributes.Username
|
||||
appended by "={}". When the Attributes.Username is set to "dn"
|
||||
then the Filter must be explicitly specified, since the default
|
||||
value of "dn={}" would not work.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- host
|
||||
type: object
|
||||
status:
|
||||
description: Status of the identity provider.
|
||||
properties:
|
||||
conditions:
|
||||
description: Represents the observations of an identity provider's
|
||||
current state.
|
||||
items:
|
||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||
type added in Kubernetes 1.19). In a future API version we can
|
||||
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time the condition
|
||||
transitioned from one status to another. This should be when
|
||||
the underlying condition changed. If that is not known, then
|
||||
using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message indicating
|
||||
details about the transition. This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation
|
||||
that the condition was set based upon. For instance, if .metadata.generation
|
||||
is currently 12, but the .status.conditions[x].observedGeneration
|
||||
is 9, the condition is out of date with respect to the current
|
||||
state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier indicating
|
||||
the reason for the condition's last transition. Producers
|
||||
of specific condition types may define expected values and
|
||||
meanings for this field, and whether the values are considered
|
||||
a guaranteed API. The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
--- Many .condition.type values are consistent across resources
|
||||
like Available, but because arbitrary conditions can be useful
|
||||
(see .node.status.conditions), the ability to deconflict is
|
||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
phase:
|
||||
default: Pending
|
||||
description: Phase summarizes the overall status of the LDAPIdentityProvider.
|
||||
enum:
|
||||
- Pending
|
||||
- Ready
|
||||
- Error
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
@ -0,0 +1,346 @@
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: v0.8.0
|
||||
creationTimestamp: null
|
||||
name: oidcidentityproviders.idp.supervisor.pinniped.dev
|
||||
spec:
|
||||
group: idp.supervisor.pinniped.dev
|
||||
names:
|
||||
categories:
|
||||
- pinniped
|
||||
- pinniped-idp
|
||||
- pinniped-idps
|
||||
kind: OIDCIdentityProvider
|
||||
listKind: OIDCIdentityProviderList
|
||||
plural: oidcidentityproviders
|
||||
singular: oidcidentityprovider
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .spec.issuer
|
||||
name: Issuer
|
||||
type: string
|
||||
- jsonPath: .status.phase
|
||||
name: Status
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: OIDCIdentityProvider describes the configuration of an upstream
|
||||
OpenID Connect identity provider.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
of an object. Servers should convert recognized schemas to the latest
|
||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind is a string value representing the REST resource this
|
||||
object represents. Servers may infer this from the endpoint the client
|
||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: Spec for configuring the identity provider.
|
||||
properties:
|
||||
authorizationConfig:
|
||||
description: AuthorizationConfig holds information about how to form
|
||||
the OAuth2 authorization request parameters to be used with this
|
||||
OIDC identity provider.
|
||||
properties:
|
||||
additionalAuthorizeParameters:
|
||||
description: additionalAuthorizeParameters are extra query parameters
|
||||
that should be included in the authorize request to your OIDC
|
||||
provider in the authorization request during an OIDC Authorization
|
||||
Code Flow. By default, no extra parameters are sent. The standard
|
||||
parameters that will be sent are "response_type", "scope", "client_id",
|
||||
"state", "nonce", "code_challenge", "code_challenge_method",
|
||||
and "redirect_uri". These parameters cannot be included in this
|
||||
setting. Additionally, the "hd" parameter cannot be included
|
||||
in this setting at this time. The "hd" parameter is used by
|
||||
Google's OIDC provider to provide a hint as to which "hosted
|
||||
domain" the user should use during login. However, Pinniped
|
||||
does not yet support validating the hosted domain in the resulting
|
||||
ID token, so it is not yet safe to use this feature of Google's
|
||||
OIDC provider with Pinniped. This setting does not influence
|
||||
the parameters sent to the token endpoint in the Resource Owner
|
||||
Password Credentials Grant. The Pinniped Supervisor requires
|
||||
that your OIDC provider returns refresh tokens to the Supervisor
|
||||
from the authorization flows. Some OIDC providers may require
|
||||
a certain value for the "prompt" parameter in order to properly
|
||||
request refresh tokens. See the documentation of your OIDC provider's
|
||||
authorization endpoint for its requirements for what to include
|
||||
in the request in order to receive a refresh token in the response,
|
||||
if anything. If your provider requires the prompt parameter
|
||||
to request a refresh token, then include it here. Also note
|
||||
that most providers also require a certain scope to be requested
|
||||
in order to receive refresh tokens. See the additionalScopes
|
||||
setting for more information about using scopes to request refresh
|
||||
tokens.
|
||||
items:
|
||||
description: Parameter is a key/value pair which represents
|
||||
a parameter in an HTTP request.
|
||||
properties:
|
||||
name:
|
||||
description: The name of the parameter. Required.
|
||||
minLength: 1
|
||||
type: string
|
||||
value:
|
||||
description: The value of the parameter.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- name
|
||||
x-kubernetes-list-type: map
|
||||
additionalScopes:
|
||||
description: 'additionalScopes are the additional scopes that
|
||||
will be requested from your OIDC provider in the authorization
|
||||
request during an OIDC Authorization Code Flow and in the token
|
||||
request during a Resource Owner Password Credentials Grant.
|
||||
Note that the "openid" scope will always be requested regardless
|
||||
of the value in this setting, since it is always required according
|
||||
to the OIDC spec. By default, when this field is not set, the
|
||||
Supervisor will request the following scopes: "openid", "offline_access",
|
||||
"email", and "profile". See https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
|
||||
for a description of the "profile" and "email" scopes. See https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
|
||||
for a description of the "offline_access" scope. This default
|
||||
value may change in future versions of Pinniped as the standard
|
||||
evolves, or as common patterns used by providers who implement
|
||||
the standard in the ecosystem evolve. By setting this list to
|
||||
anything other than an empty list, you are overriding the default
|
||||
value, so you may wish to include some of "offline_access",
|
||||
"email", and "profile" in your override list. If you do not
|
||||
want any of these scopes to be requested, you may set this list
|
||||
to contain only "openid". Some OIDC providers may also require
|
||||
a scope to get access to the user''s group membership, in which
|
||||
case you may wish to include it in this list. Sometimes the
|
||||
scope to request the user''s group membership is called "groups",
|
||||
but unfortunately this is not specified in the OIDC standard.
|
||||
Generally speaking, you should include any scopes required to
|
||||
cause the appropriate claims to be the returned by your OIDC
|
||||
provider in the ID token or userinfo endpoint results for those
|
||||
claims which you would like to use in the oidcClaims settings
|
||||
to determine the usernames and group memberships of your Kubernetes
|
||||
users. See your OIDC provider''s documentation for more information
|
||||
about what scopes are available to request claims. Additionally,
|
||||
the Pinniped Supervisor requires that your OIDC provider returns
|
||||
refresh tokens to the Supervisor from these authorization flows.
|
||||
For most OIDC providers, the scope required to receive refresh
|
||||
tokens will be "offline_access". See the documentation of your
|
||||
OIDC provider''s authorization and token endpoints for its requirements
|
||||
for what to include in the request in order to receive a refresh
|
||||
token in the response, if anything. Note that it may be safe
|
||||
to send "offline_access" even to providers which do not require
|
||||
it, since the provider may ignore scopes that it does not understand
|
||||
or require (see https://datatracker.ietf.org/doc/html/rfc6749#section-3.3).
|
||||
In the unusual case that you must avoid sending the "offline_access"
|
||||
scope, then you must override the default value of this setting.
|
||||
This is required if your OIDC provider will reject the request
|
||||
when it includes "offline_access" (e.g. GitLab''s OIDC provider).'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
allowPasswordGrant:
|
||||
description: allowPasswordGrant, when true, will allow the use
|
||||
of OAuth 2.0's Resource Owner Password Credentials Grant (see
|
||||
https://datatracker.ietf.org/doc/html/rfc6749#section-4.3) to
|
||||
authenticate to the OIDC provider using a username and password
|
||||
without a web browser, in addition to the usual browser-based
|
||||
OIDC Authorization Code Flow. The Resource Owner Password Credentials
|
||||
Grant is not officially part of the OIDC specification, so it
|
||||
may not be supported by your OIDC provider. If your OIDC provider
|
||||
supports returning ID tokens from a Resource Owner Password
|
||||
Credentials Grant token request, then you can choose to set
|
||||
this field to true. This will allow end users to choose to present
|
||||
their username and password to the kubectl CLI (using the Pinniped
|
||||
plugin) to authenticate to the cluster, without using a web
|
||||
browser to log in as is customary in OIDC Authorization Code
|
||||
Flow. This may be convenient for users, especially for identities
|
||||
from your OIDC provider which are not intended to represent
|
||||
a human actor, such as service accounts performing actions in
|
||||
a CI/CD environment. Even if your OIDC provider supports it,
|
||||
you may wish to disable this behavior by setting this field
|
||||
to false when you prefer to only allow users of this OIDCIdentityProvider
|
||||
to log in via the browser-based OIDC Authorization Code Flow.
|
||||
Using the Resource Owner Password Credentials Grant means that
|
||||
the Pinniped CLI and Pinniped Supervisor will directly handle
|
||||
your end users' passwords (similar to LDAPIdentityProvider),
|
||||
and you will not be able to require multi-factor authentication
|
||||
or use the other web-based login features of your OIDC provider
|
||||
during Resource Owner Password Credentials Grant logins. allowPasswordGrant
|
||||
defaults to false.
|
||||
type: boolean
|
||||
type: object
|
||||
claims:
|
||||
description: Claims provides the names of token claims that will be
|
||||
used when inspecting an identity from this OIDC identity provider.
|
||||
properties:
|
||||
additionalClaimMappings:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: AdditionalClaimMappings allows for additional arbitrary
|
||||
upstream claim values to be mapped into the "additionalClaims"
|
||||
claim of the ID tokens generated by the Supervisor. This should
|
||||
be specified as a map of new claim names as the keys, and upstream
|
||||
claim names as the values. These new claim names will be nested
|
||||
under the top-level "additionalClaims" claim in ID tokens generated
|
||||
by the Supervisor when this OIDCIdentityProvider was used for
|
||||
user authentication. These claims will be made available to
|
||||
all clients. This feature is not required to use the Supervisor
|
||||
to provide authentication for Kubernetes clusters, but can be
|
||||
used when using the Supervisor for other authentication purposes.
|
||||
When this map is empty or the upstream claims are not available,
|
||||
the "additionalClaims" claim will be excluded from the ID tokens
|
||||
generated by the Supervisor.
|
||||
type: object
|
||||
groups:
|
||||
description: Groups provides the name of the ID token claim or
|
||||
userinfo endpoint response claim that will be used to ascertain
|
||||
the groups to which an identity belongs. By default, the identities
|
||||
will not include any group memberships when this setting is
|
||||
not configured.
|
||||
type: string
|
||||
username:
|
||||
description: Username provides the name of the ID token claim
|
||||
or userinfo endpoint response claim that will be used to ascertain
|
||||
an identity's username. When not set, the username will be an
|
||||
automatically constructed unique string which will include the
|
||||
issuer URL of your OIDC provider along with the value of the
|
||||
"sub" (subject) claim from the ID token.
|
||||
type: string
|
||||
type: object
|
||||
client:
|
||||
description: OIDCClient contains OIDC client information to be used
|
||||
used with this OIDC identity provider.
|
||||
properties:
|
||||
secretName:
|
||||
description: SecretName contains the name of a namespace-local
|
||||
Secret object that provides the clientID and clientSecret for
|
||||
an OIDC client. If only the SecretName is specified in an OIDCClient
|
||||
struct, then it is expected that the Secret is of type "secrets.pinniped.dev/oidc-client"
|
||||
with keys "clientID" and "clientSecret".
|
||||
type: string
|
||||
required:
|
||||
- secretName
|
||||
type: object
|
||||
issuer:
|
||||
description: Issuer is the issuer URL of this OIDC identity provider,
|
||||
i.e., where to fetch /.well-known/openid-configuration.
|
||||
minLength: 1
|
||||
pattern: ^https://
|
||||
type: string
|
||||
tls:
|
||||
description: TLS configuration for discovery/JWKS requests to the
|
||||
issuer.
|
||||
properties:
|
||||
certificateAuthorityData:
|
||||
description: X.509 Certificate Authority (base64-encoded PEM bundle).
|
||||
If omitted, a default set of system roots will be trusted.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- client
|
||||
- issuer
|
||||
type: object
|
||||
status:
|
||||
description: Status of the identity provider.
|
||||
properties:
|
||||
conditions:
|
||||
description: Represents the observations of an identity provider's
|
||||
current state.
|
||||
items:
|
||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||
type added in Kubernetes 1.19). In a future API version we can
|
||||
switch to using the upstream type. See https://github.com/kubernetes/apimachinery/blob/v0.19.0/pkg/apis/meta/v1/types.go#L1353-L1413.
|
||||
properties:
|
||||
lastTransitionTime:
|
||||
description: lastTransitionTime is the last time the condition
|
||||
transitioned from one status to another. This should be when
|
||||
the underlying condition changed. If that is not known, then
|
||||
using the time when the API field changed is acceptable.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: message is a human readable message indicating
|
||||
details about the transition. This may be an empty string.
|
||||
maxLength: 32768
|
||||
type: string
|
||||
observedGeneration:
|
||||
description: observedGeneration represents the .metadata.generation
|
||||
that the condition was set based upon. For instance, if .metadata.generation
|
||||
is currently 12, but the .status.conditions[x].observedGeneration
|
||||
is 9, the condition is out of date with respect to the current
|
||||
state of the instance.
|
||||
format: int64
|
||||
minimum: 0
|
||||
type: integer
|
||||
reason:
|
||||
description: reason contains a programmatic identifier indicating
|
||||
the reason for the condition's last transition. Producers
|
||||
of specific condition types may define expected values and
|
||||
meanings for this field, and whether the values are considered
|
||||
a guaranteed API. The value should be a CamelCase string.
|
||||
This field may not be empty.
|
||||
maxLength: 1024
|
||||
minLength: 1
|
||||
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||
type: string
|
||||
status:
|
||||
description: status of the condition, one of True, False, Unknown.
|
||||
enum:
|
||||
- "True"
|
||||
- "False"
|
||||
- Unknown
|
||||
type: string
|
||||
type:
|
||||
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||
--- Many .condition.type values are consistent across resources
|
||||
like Available, but because arbitrary conditions can be useful
|
||||
(see .node.status.conditions), the ability to deconflict is
|
||||
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
|
||||
maxLength: 316
|
||||
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||
type: string
|
||||
required:
|
||||
- lastTransitionTime
|
||||
- message
|
||||
- reason
|
||||
- status
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
x-kubernetes-list-map-keys:
|
||||
- type
|
||||
x-kubernetes-list-type: map
|
||||
phase:
|
||||
default: Pending
|
||||
description: Phase summarizes the overall status of the OIDCIdentityProvider.
|
||||
enum:
|
||||
- Pending
|
||||
- Ready
|
||||
- Error
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- spec
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
152
deploy_carvel/supervisor/config/rbac.yaml
Normal file
152
deploy_carvel/supervisor/config/rbac.yaml
Normal file
@ -0,0 +1,152 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
#@ load("helpers.lib.yaml", "labels", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix", "pinnipedDevAPIGroupWithPrefix")
|
||||
|
||||
#! Give permission to various objects within the app's own namespace
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: [secrets]
|
||||
verbs: [create, get, list, patch, update, watch, delete]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||
resources: [federationdomains]
|
||||
verbs: [get, list, watch]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||
resources: [federationdomains/status]
|
||||
verbs: [get, patch, update]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||
resources: [oidcclients]
|
||||
verbs: [get, list, watch]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||
resources: [oidcclients/status]
|
||||
verbs: [get, patch, update]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||
resources: [oidcidentityproviders]
|
||||
verbs: [get, list, watch]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||
resources: [oidcidentityproviders/status]
|
||||
verbs: [get, patch, update]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||
resources: [ldapidentityproviders]
|
||||
verbs: [get, list, watch]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||
resources: [ldapidentityproviders/status]
|
||||
verbs: [get, patch, update]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||
resources: [activedirectoryidentityproviders]
|
||||
verbs: [get, list, watch]
|
||||
- apiGroups:
|
||||
- #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||
resources: [activedirectoryidentityproviders/status]
|
||||
verbs: [get, patch, update]
|
||||
#! We want to be able to read pods/replicasets/deployment so we can learn who our deployment is to set
|
||||
#! as an owner reference.
|
||||
- apiGroups: [""]
|
||||
resources: [pods]
|
||||
verbs: [get]
|
||||
- apiGroups: [apps]
|
||||
resources: [replicasets,deployments]
|
||||
verbs: [get]
|
||||
- apiGroups: [ coordination.k8s.io ]
|
||||
resources: [ leases ]
|
||||
verbs: [ create, get, update ]
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: #@ defaultResourceName()
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give permissions for a special configmap of CA bundles that is needed by aggregated api servers
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("extension-apiserver-authentication-reader")
|
||||
namespace: kube-system
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: extension-apiserver-authentication-reader
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give permissions for subjectaccessreviews, tokenreview that is needed by aggregated api servers
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceName()
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: system:auth-delegator
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
#! Give permission to various cluster-scoped objects
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||
labels: #@ labels()
|
||||
rules:
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ namespaces ]
|
||||
verbs: [ get, list, watch ]
|
||||
- apiGroups: [ apiregistration.k8s.io ]
|
||||
resources: [ apiservices ]
|
||||
verbs: [ get, list, patch, update, watch ]
|
||||
- apiGroups: [ admissionregistration.k8s.io ]
|
||||
resources: [ validatingwebhookconfigurations, mutatingwebhookconfigurations ]
|
||||
verbs: [ get, list, watch ]
|
||||
- apiGroups: [ flowcontrol.apiserver.k8s.io ]
|
||||
resources: [ flowschemas, prioritylevelconfigurations ]
|
||||
verbs: [ get, list, watch ]
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||
labels: #@ labels()
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: #@ defaultResourceName()
|
||||
namespace: #@ namespace()
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: #@ defaultResourceNameWithSuffix("aggregated-api-server")
|
||||
apiGroup: rbac.authorization.k8s.io
|
115
deploy_carvel/supervisor/config/service.yaml
Normal file
115
deploy_carvel/supervisor/config/service.yaml
Normal file
@ -0,0 +1,115 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:data", "data")
|
||||
#@ load("@ytt:assert", "assert")
|
||||
#@ load("helpers.lib.yaml", "labels", "deploymentPodLabel", "namespace", "defaultResourceName", "defaultResourceNameWithSuffix")
|
||||
|
||||
#@ if hasattr(data.values, "service_http_nodeport_port"):
|
||||
#@ assert.fail('value "service_http_nodeport_port" has been renamed to "deprecated_service_http_nodeport_port" and will be removed in a future release')
|
||||
#@ end
|
||||
#@ if hasattr(data.values, "service_http_nodeport_nodeport"):
|
||||
#@ assert.fail('value "service_http_nodeport_nodeport" has been renamed to "deprecated_service_http_nodeport_nodeport" and will be removed in a future release')
|
||||
#@ end
|
||||
#@ if hasattr(data.values, "service_http_loadbalancer_port"):
|
||||
#@ assert.fail('value "service_http_loadbalancer_port" has been renamed to "deprecated_service_http_loadbalancer_port" and will be removed in a future release')
|
||||
#@ end
|
||||
#@ if hasattr(data.values, "service_http_clusterip_port"):
|
||||
#@ assert.fail('value "service_http_clusterip_port" has been renamed to "deprecated_service_http_clusterip_port" and will be removed in a future release')
|
||||
#@ end
|
||||
|
||||
#@ if data.values.deprecated_service_http_nodeport_port or data.values.service_https_nodeport_port:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("nodeport")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||
annotations:
|
||||
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||
spec:
|
||||
type: NodePort
|
||||
selector: #@ deploymentPodLabel()
|
||||
ports:
|
||||
#@ if data.values.deprecated_service_http_nodeport_port:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: #@ data.values.deprecated_service_http_nodeport_port
|
||||
targetPort: 8080
|
||||
#@ if data.values.deprecated_service_http_nodeport_nodeport:
|
||||
nodePort: #@ data.values.deprecated_service_http_nodeport_nodeport
|
||||
#@ end
|
||||
#@ end
|
||||
#@ if data.values.service_https_nodeport_port:
|
||||
- name: https
|
||||
protocol: TCP
|
||||
port: #@ data.values.service_https_nodeport_port
|
||||
targetPort: 8443
|
||||
#@ if data.values.service_https_nodeport_nodeport:
|
||||
nodePort: #@ data.values.service_https_nodeport_nodeport
|
||||
#@ end
|
||||
#@ end
|
||||
#@ end
|
||||
|
||||
#@ if data.values.deprecated_service_http_clusterip_port or data.values.service_https_clusterip_port:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("clusterip")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||
annotations:
|
||||
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector: #@ deploymentPodLabel()
|
||||
ports:
|
||||
#@ if data.values.deprecated_service_http_clusterip_port:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: #@ data.values.deprecated_service_http_clusterip_port
|
||||
targetPort: 8080
|
||||
#@ end
|
||||
#@ if data.values.service_https_clusterip_port:
|
||||
- name: https
|
||||
protocol: TCP
|
||||
port: #@ data.values.service_https_clusterip_port
|
||||
targetPort: 8443
|
||||
#@ end
|
||||
#@ end
|
||||
|
||||
#@ if data.values.deprecated_service_http_loadbalancer_port or data.values.service_https_loadbalancer_port:
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: #@ defaultResourceNameWithSuffix("loadbalancer")
|
||||
namespace: #@ namespace()
|
||||
labels: #@ labels()
|
||||
#! prevent kapp from altering the selector of our services to match kubectl behavior
|
||||
annotations:
|
||||
kapp.k14s.io/disable-default-label-scoping-rules: ""
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
selector: #@ deploymentPodLabel()
|
||||
#@ if data.values.service_loadbalancer_ip:
|
||||
loadBalancerIP: #@ data.values.service_loadbalancer_ip
|
||||
#@ end
|
||||
ports:
|
||||
#@ if data.values.deprecated_service_http_loadbalancer_port:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: #@ data.values.deprecated_service_http_loadbalancer_port
|
||||
targetPort: 8080
|
||||
#@ end
|
||||
#@ if data.values.service_https_loadbalancer_port:
|
||||
- name: https
|
||||
protocol: TCP
|
||||
port: #@ data.values.service_https_loadbalancer_port
|
||||
targetPort: 8443
|
||||
#@ end
|
||||
#@ end
|
170
deploy_carvel/supervisor/config/values.yaml
Normal file
170
deploy_carvel/supervisor/config/values.yaml
Normal file
@ -0,0 +1,170 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@data/values-schema
|
||||
---
|
||||
#@schema/desc "Namespace of pinniped-supervisor"
|
||||
app_name: pinniped-supervisor
|
||||
#@schema/desc "Creates a new namespace statically in yaml with the given name and installs the app into that namespace."
|
||||
namespace: pinniped-supervisor
|
||||
#! If specified, assumes that a namespace of the given name already exists and installs the app into that namespace.
|
||||
#! If both `namespace` and `into_namespace` are specified, then only `into_namespace` is used.
|
||||
#@schema/desc "Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???"
|
||||
#@schema/nullable
|
||||
into_namespace: my-preexisting-namespace
|
||||
|
||||
#! All resources created statically by yaml at install-time and all resources created dynamically
|
||||
#! by controllers at runtime will be labelled with `app: $app_name` and also with the labels
|
||||
#! specified here. The value of `custom_labels` must be a map of string keys to string values.
|
||||
#! The app can be uninstalled either by:
|
||||
#! 1. Deleting the static install-time yaml resources including the static namespace, which will cascade and also delete
|
||||
#! resources that were dynamically created by controllers at runtime
|
||||
#! 2. Or, deleting all resources by label, which does not assume that there was a static install-time yaml namespace.
|
||||
#@schema/desc "All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here."
|
||||
custom_labels: {} #! e.g. {myCustomLabelName: myCustomLabelValue, otherCustomLabelName: otherCustomLabelValue}
|
||||
|
||||
#@schema/desc "Specify how many replicas of the Pinniped server to run."
|
||||
replicas: 2
|
||||
|
||||
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||
image_repo: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||
#@schema/nullable
|
||||
image_digest: sha256:f3c4fdfd3ef865d4b97a1fd295d94acc3f0c654c46b6f27ffad5cf80216903c8
|
||||
#@schema/desc "Specify either an image_digest or an image_tag. If both are given, only image_digest will be used."
|
||||
image_tag: latest
|
||||
|
||||
#! TODO: preserve even if this file is revised!
|
||||
#@schema/nullable
|
||||
package_image_repo: docker.io/benjaminapetersen/some-pinniped-supervisor-package
|
||||
#@schema/nullable
|
||||
package_image_digest: sha256:123456
|
||||
#@schema/nullable
|
||||
package_image_tag: latest
|
||||
#! prob should not be nullable
|
||||
#@schema/nullable
|
||||
package_version: 1.2.3
|
||||
|
||||
#! Specifies a secret to be used when pulling the above `image_repo` container image.
|
||||
#! Can be used when the above image_repo is a private registry.
|
||||
#! Typically the value would be the output of: kubectl create secret docker-registry x --docker-server=https://example.io --docker-username="USERNAME" --docker-password="PASSWORD" --dry-run=client -o json | jq -r '.data[".dockerconfigjson"]'
|
||||
#! Optional.
|
||||
#@schema/description "Specifies a secret to be used when pulling the above `image_repo` container image. Can be used when the image_repo is a private registry."
|
||||
#@schema/nullable
|
||||
image_pull_dockerconfigjson: {"auths":{"https://registry.example.com":{"username":"USERNAME","password":"PASSWORD","auth":"BASE64_ENCODED_USERNAME_COLON_PASSWORD"}}}
|
||||
|
||||
#! Specify how to expose the Supervisor app's HTTPS port as a Service.
|
||||
#! Typically, you would set a value for only one of the following service types.
|
||||
#! Setting any of these values means that a Service of that type will be created. They are all optional.
|
||||
#! Note that all port numbers should be numbers (not strings), i.e. use ytt's `--data-value-yaml` instead of `--data-value`.
|
||||
#! Several of these values have been deprecated and will be removed in a future release. Their names have been changed to
|
||||
#! mark them as deprecated and to make it obvious upon upgrade to anyone who was using them that they have been deprecated.
|
||||
#@schema/desc "will be removed in a future release; when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234"
|
||||
#@schema/nullable
|
||||
deprecated_service_http_nodeport_port: 31234
|
||||
#@schema/desc "will be removed in a future release; the `nodePort` value of the NodePort Service, optional when `deprecated_service_http_nodeport_port` is specified; e.g. 31234"
|
||||
#@schema/nullable
|
||||
deprecated_service_http_nodeport_nodeport: 31234
|
||||
#@schema/desc "will be removed in a future release; when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443"
|
||||
#@schema/nullable
|
||||
deprecated_service_http_loadbalancer_port: 8443
|
||||
#@schema/desc "will be removed in a future release; when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443"
|
||||
#@schema/nullable
|
||||
deprecated_service_http_clusterip_port: 8443
|
||||
#@schema/desc "when specified, creates a NodePort Service with this `port` value, with port 8443 as its `targetPort`; e.g. 31243"
|
||||
#@schema/nullable
|
||||
service_https_nodeport_port: 31243
|
||||
#@schema/desc "the `nodePort` value of the NodePort Service, optional when `service_https_nodeport_port` is specified; e.g. 31243"
|
||||
#@schema/nullable
|
||||
service_https_nodeport_nodeport: 31243
|
||||
#@schema/desc "when specified, creates a LoadBalancer Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443"
|
||||
#@schema/nullable
|
||||
service_https_loadbalancer_port: 8443
|
||||
#@schema/desc "when specified, creates a ClusterIP Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443"
|
||||
#@schema/nullable
|
||||
service_https_clusterip_port: 8443
|
||||
#! Optional.
|
||||
#@schema/desc "The `loadBalancerIP` value of the LoadBalancer Service. Ignored unless service_https_loadbalancer_port is provided. e.g. 1.2.3.4"
|
||||
#@schema/nullable
|
||||
service_loadbalancer_ip: 1.2.3.4
|
||||
|
||||
#@schema/desc 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||
#@schema/nullable
|
||||
log_level: info #! By default, when this value is left unset, only warnings and errors are printed. There is no way to suppress warning and error logs.
|
||||
#@schema/desc "Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json."
|
||||
#@schema/nullable
|
||||
deprecated_log_format: json
|
||||
|
||||
#@schema/desc "run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice"
|
||||
run_as_user: 65532
|
||||
#@schema/desc "run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice"
|
||||
run_as_group: 65532
|
||||
|
||||
#@schema/desc "Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc."
|
||||
api_group_suffix: pinniped.dev
|
||||
|
||||
#! Optional.
|
||||
#@schema/desc "Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Supervisor containers. These will be used when the Supervisor makes backend-to-backend calls to upstream identity providers using HTTPS, e.g. when the Supervisor fetches discovery documents, JWKS keys, and tokens from an upstream OIDC Provider. The Supervisor never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY."
|
||||
#@schema/nullable
|
||||
https_proxy: http://proxy.example.com
|
||||
#@schema/desc "NO_PROXY environment variable. do not proxy Kubernetes endpoints"
|
||||
no_proxy: "$(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local"
|
||||
|
||||
#! Control the HTTP and HTTPS listeners of the Supervisor.
|
||||
#!
|
||||
#! The schema of this config is as follows:
|
||||
#!
|
||||
#! endpoints:
|
||||
#! https:
|
||||
#! network: tcp | unix | disabled
|
||||
#! address: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix
|
||||
#! http:
|
||||
#! network: same as above
|
||||
#! address: same as above, except that when network=tcp then the address is only allowed to bind to loopback interfaces
|
||||
#!
|
||||
#! Setting network to disabled turns off that particular listener.
|
||||
#! See https://pkg.go.dev/net#Listen and https://pkg.go.dev/net#Dial for a description of what can be
|
||||
#! specified in the address parameter based on the given network parameter. To aid in the use of unix
|
||||
#! domain sockets, a writable empty dir volume is mounted at /pinniped_socket when network is set to "unix."
|
||||
#!
|
||||
#! The current defaults are:
|
||||
#!
|
||||
#! endpoints:
|
||||
#! https:
|
||||
#! network: tcp
|
||||
#! address: :8443
|
||||
#! http:
|
||||
#! network: disabled
|
||||
#!
|
||||
#! These defaults mean: For HTTPS listening, bind to all interfaces using TCP on port 8443.
|
||||
#! Disable HTTP listening by default.
|
||||
#!
|
||||
#! The HTTP listener can only be bound to loopback interfaces. This allows the listener to accept
|
||||
#! traffic from within the pod, e.g. from a service mesh sidecar. The HTTP listener should not be
|
||||
#! used to accept traffic from outside the pod, since that would mean that the network traffic could be
|
||||
#! transmitted unencrypted. The HTTPS listener should be used instead to accept traffic from outside the pod.
|
||||
#! Ingresses and load balancers that terminate TLS connections should re-encrypt the data and route traffic
|
||||
#! to the HTTPS listener. Unix domain sockets may also be used for integrations with service meshes.
|
||||
#!
|
||||
#! Changing the HTTPS port number must be accompanied by matching changes to the service and deployment
|
||||
#! manifests. Changes to the HTTPS listener must be coordinated with the deployment health checks.
|
||||
#!
|
||||
#! Optional.
|
||||
#@schema/desc "Control the HTTP and HTTPS listeners of the Supervisor."
|
||||
#@schema/nullable
|
||||
endpoints:
|
||||
https:
|
||||
network: tcp | unix | disabled
|
||||
address: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix
|
||||
|
||||
#! Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used.
|
||||
#! When deprecated_insecure_accept_external_unencrypted_http_requests is true, the HTTP listener is allowed to bind to any
|
||||
#! interface, including interfaces that are listening for traffic from outside the pod. This value is being introduced
|
||||
#! to ease the transition to the new loopback interface validation for the HTTP port for any users who need more time
|
||||
#! to change their ingress strategy to avoid using plain HTTP into the Supervisor pods.
|
||||
#! This value is immediately deprecated upon its introduction. It will be removed in some future release, at which time
|
||||
#! traffic from outside the pod will need to be sent to the HTTPS listener instead, with no simple workaround available.
|
||||
#! Allowed values are true (boolean), "true" (string), false (boolean), and "false" (string). The default is false.
|
||||
#! Optional.
|
||||
#@schema/desc "Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used."
|
||||
deprecated_insecure_accept_external_unencrypted_http_requests: false
|
63
deploy_carvel/supervisor/config/z0_crd_overlay.yaml
Normal file
63
deploy_carvel/supervisor/config/z0_crd_overlay.yaml
Normal file
@ -0,0 +1,63 @@
|
||||
#! Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
#! SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#@ load("@ytt:overlay", "overlay")
|
||||
#@ load("helpers.lib.yaml", "labels", "pinnipedDevAPIGroupWithPrefix")
|
||||
#@ load("@ytt:data", "data")
|
||||
|
||||
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"federationdomains.config.supervisor.pinniped.dev"}}), expects=1
|
||||
---
|
||||
metadata:
|
||||
#@overlay/match missing_ok=True
|
||||
labels: #@ labels()
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("federationdomains.config.supervisor")
|
||||
spec:
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||
|
||||
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"oidcidentityproviders.idp.supervisor.pinniped.dev"}}), expects=1
|
||||
---
|
||||
metadata:
|
||||
#@overlay/match missing_ok=True
|
||||
labels: #@ labels()
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("oidcidentityproviders.idp.supervisor")
|
||||
spec:
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||
|
||||
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"ldapidentityproviders.idp.supervisor.pinniped.dev"}}), expects=1
|
||||
---
|
||||
metadata:
|
||||
#@overlay/match missing_ok=True
|
||||
labels: #@ labels()
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("ldapidentityproviders.idp.supervisor")
|
||||
spec:
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||
|
||||
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"activedirectoryidentityproviders.idp.supervisor.pinniped.dev"}}), expects=1
|
||||
---
|
||||
metadata:
|
||||
#@overlay/match missing_ok=True
|
||||
labels: #@ labels()
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("activedirectoryidentityproviders.idp.supervisor")
|
||||
spec:
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("idp.supervisor")
|
||||
|
||||
#@overlay/match by=overlay.subset({"kind": "CustomResourceDefinition", "metadata":{"name":"oidcclients.config.supervisor.pinniped.dev"}}), expects=1
|
||||
---
|
||||
metadata:
|
||||
#@overlay/match missing_ok=True
|
||||
labels: #@ labels()
|
||||
name: #@ pinnipedDevAPIGroupWithPrefix("oidcclients.config.supervisor")
|
||||
spec:
|
||||
group: #@ pinnipedDevAPIGroupWithPrefix("config.supervisor")
|
||||
versions:
|
||||
#@overlay/match by=overlay.all, expects="1+"
|
||||
- schema:
|
||||
openAPIV3Schema:
|
||||
#@overlay/match by=overlay.subset({"metadata":{"type":"object"}}), expects=1
|
||||
properties:
|
||||
metadata:
|
||||
#@overlay/match missing_ok=True
|
||||
properties:
|
||||
name:
|
||||
pattern: ^client\.oauth\.pinniped\.dev-
|
||||
type: string
|
13
deploy_carvel/supervisor/metadata.yml
Normal file
13
deploy_carvel/supervisor/metadata.yml
Normal file
@ -0,0 +1,13 @@
|
||||
#@ load("@ytt:data", "data") # for reading data values (generated via ytt's data-values-schema-inspect mode).
|
||||
#@ load("@ytt:yaml", "yaml") # for dynamically decoding the output of ytt's data-values-schema-inspect
|
||||
---
|
||||
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||
kind: PackageMetadata
|
||||
metadata:
|
||||
name: supervisor.pinniped.dev
|
||||
spec:
|
||||
displayName: "Pinniped Supervisor"
|
||||
longDescription: "Pinniped supervisor allows seamless login across one or many Kubernetes clusters including AKS, EKS and GKE"
|
||||
shortDescription: "Pinniped supervisor provides login capabilities"
|
||||
categories:
|
||||
- auth
|
32
deploy_carvel/supervisor/package-template.yml
Normal file
32
deploy_carvel/supervisor/package-template.yml
Normal file
@ -0,0 +1,32 @@
|
||||
#@ load("@ytt:data", "data") # for reading data values (generated via ytt's data-values-schema-inspect mode).
|
||||
#@ load("@ytt:yaml", "yaml") # for dynamically decoding the output of ytt's data-values-schema-inspect
|
||||
---
|
||||
apiVersion: data.packaging.carvel.dev/v1alpha1
|
||||
kind: Package
|
||||
metadata:
|
||||
name: #@ "supervisor.pinniped.dev." + data.values.package_version
|
||||
spec:
|
||||
refName: supervisor.pinniped.dev
|
||||
version: #@ data.values.package_version
|
||||
releaseNotes: |
|
||||
Initial release of the pinniped supervisor package
|
||||
licenses:
|
||||
- "Apache-2.0"
|
||||
valuesSchema:
|
||||
openAPIv3: #@ yaml.decode(data.values.openapi)["components"]["schemas"]["dataValues"]
|
||||
template:
|
||||
spec:
|
||||
fetch:
|
||||
- imgpkgBundle:
|
||||
#! image: #@ data.values.package_image_repo + "/packages/:" + data.values.package_version
|
||||
image: #@ data.values.package_image_repo
|
||||
template:
|
||||
- ytt:
|
||||
paths:
|
||||
- "config/"
|
||||
- kbld:
|
||||
paths:
|
||||
- ".imgpkg/images.yml"
|
||||
- "-"
|
||||
deploy:
|
||||
- kapp: {}
|
180
deploy_carvel/supervisor/schema-openapi.yml
Normal file
180
deploy_carvel/supervisor/schema-openapi.yml
Normal file
@ -0,0 +1,180 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
version: 0.1.0
|
||||
title: Schema for data values, generated by ytt
|
||||
paths: {}
|
||||
components:
|
||||
schemas:
|
||||
dataValues:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
app_name:
|
||||
type: string
|
||||
description: Namespace of pinniped-supervisor
|
||||
default: pinniped-supervisor
|
||||
namespace:
|
||||
type: string
|
||||
description: Creates a new namespace statically in yaml with the given name and installs the app into that namespace.
|
||||
default: pinniped-supervisor
|
||||
into_namespace:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Overrides namespace. This is actually confusingly worded. TODO: CAN WE REWRITE THIS ONE???'
|
||||
default: null
|
||||
custom_labels:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: 'All resources created statically by yaml at install-time and all resources created dynamically by controllers at runtime will be labelled with `app: $app_name` and also with the labels specified here.'
|
||||
properties: {}
|
||||
replicas:
|
||||
type: integer
|
||||
description: Specify how many replicas of the Pinniped server to run.
|
||||
default: 2
|
||||
image_repo:
|
||||
type: string
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: projects.registry.vmware.com/pinniped/pinniped-server
|
||||
image_digest:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: null
|
||||
image_tag:
|
||||
type: string
|
||||
description: Specify either an image_digest or an image_tag. If both are given, only image_digest will be used.
|
||||
default: latest
|
||||
package_image_repo:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_image_digest:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_image_tag:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
package_version:
|
||||
type: string
|
||||
nullable: true
|
||||
default: null
|
||||
image_pull_dockerconfigjson:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
nullable: true
|
||||
properties:
|
||||
auths:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
https://registry.example.com:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
default: USERNAME
|
||||
password:
|
||||
type: string
|
||||
default: PASSWORD
|
||||
auth:
|
||||
type: string
|
||||
default: BASE64_ENCODED_USERNAME_COLON_PASSWORD
|
||||
deprecated_service_http_nodeport_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: will be removed in a future release; when specified, creates a NodePort Service with this `port` value, with port 8080 as its `targetPort`; e.g. 31234
|
||||
default: null
|
||||
deprecated_service_http_nodeport_nodeport:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: will be removed in a future release; the `nodePort` value of the NodePort Service, optional when `deprecated_service_http_nodeport_port` is specified; e.g. 31234
|
||||
default: null
|
||||
deprecated_service_http_loadbalancer_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: will be removed in a future release; when specified, creates a LoadBalancer Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||
default: null
|
||||
deprecated_service_http_clusterip_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: will be removed in a future release; when specified, creates a ClusterIP Service with this `port` value, with port 8080 as its `targetPort`; e.g. 8443
|
||||
default: null
|
||||
service_https_nodeport_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: when specified, creates a NodePort Service with this `port` value, with port 8443 as its `targetPort`; e.g. 31243
|
||||
default: null
|
||||
service_https_nodeport_nodeport:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: the `nodePort` value of the NodePort Service, optional when `service_https_nodeport_port` is specified; e.g. 31243
|
||||
default: null
|
||||
service_https_loadbalancer_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: when specified, creates a LoadBalancer Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||
default: null
|
||||
service_https_clusterip_port:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: when specified, creates a ClusterIP Service with this `port` value, with port 8443 as its `targetPort`; e.g. 8443
|
||||
default: null
|
||||
service_loadbalancer_ip:
|
||||
type: string
|
||||
nullable: true
|
||||
description: The `loadBalancerIP` value of the LoadBalancer Service. Ignored unless service_https_loadbalancer_port is provided. e.g. 1.2.3.4
|
||||
default: null
|
||||
log_level:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Specify the verbosity of logging: info ("nice to know" information), debug (developer information), trace (timing information), or all (kitchen sink). Do not use trace or all on production systems, as credentials may get logged.'
|
||||
default: null
|
||||
deprecated_log_format:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 'Specify the format of logging: json (for machine parsable logs) and text (for legacy klog formatted logs). By default, when this value is left unset, logs are formatted in json. This configuration is deprecated and will be removed in a future release at which point logs will always be formatted as json.'
|
||||
default: null
|
||||
run_as_user:
|
||||
type: integer
|
||||
description: run_as_user specifies the user ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
default: 65532
|
||||
run_as_group:
|
||||
type: integer
|
||||
description: run_as_group specifies the group ID that will own the process, see the Dockerfile for the reasoning behind this choice
|
||||
default: 65532
|
||||
api_group_suffix:
|
||||
type: string
|
||||
description: Specify the API group suffix for all Pinniped API groups. By default, this is set to pinniped.dev, so Pinniped API groups will look like foo.pinniped.dev, authentication.concierge.pinniped.dev, etc. As an example, if this is set to tuna.io, then Pinniped API groups will look like foo.tuna.io. authentication.concierge.tuna.io, etc.
|
||||
default: pinniped.dev
|
||||
https_proxy:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Set the standard golang HTTPS_PROXY and NO_PROXY environment variables on the Supervisor containers. These will be used when the Supervisor makes backend-to-backend calls to upstream identity providers using HTTPS, e.g. when the Supervisor fetches discovery documents, JWKS keys, and tokens from an upstream OIDC Provider. The Supervisor never makes insecure HTTP calls, so there is no reason to set HTTP_PROXY.
|
||||
default: null
|
||||
no_proxy:
|
||||
type: string
|
||||
description: NO_PROXY environment variable. do not proxy Kubernetes endpoints
|
||||
default: $(KUBERNETES_SERVICE_HOST),169.254.169.254,127.0.0.1,localhost,.svc,.cluster.local
|
||||
endpoints:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
nullable: true
|
||||
description: Control the HTTP and HTTPS listeners of the Supervisor.
|
||||
properties:
|
||||
https:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
network:
|
||||
type: string
|
||||
default: tcp | unix | disabled
|
||||
address:
|
||||
type: string
|
||||
default: host:port when network=tcp or /pinniped_socket/socketfile.sock when network=unix
|
||||
deprecated_insecure_accept_external_unencrypted_http_requests:
|
||||
type: boolean
|
||||
description: Optionally override the validation on the endpoints.http value which checks that only loopback interfaces are used.
|
||||
default: false
|
@ -5,9 +5,88 @@
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
#
|
||||
# Helper functions
|
||||
#
|
||||
function log_note() {
|
||||
GREEN='\033[0;32m'
|
||||
NC='\033[0m'
|
||||
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||
echo -e "${GREEN}$*${NC}"
|
||||
else
|
||||
echo "$*"
|
||||
fi
|
||||
}
|
||||
|
||||
function log_error() {
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
if [[ ${COLORTERM:-unknown} =~ ^(truecolor|24bit)$ ]]; then
|
||||
echo -e "🙁${RED} Error: $* ${NC}"
|
||||
else
|
||||
echo ":( Error: $*"
|
||||
fi
|
||||
}
|
||||
|
||||
log_note "begin setting up kind cluster with local registry..."
|
||||
|
||||
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
|
||||
cd "${ROOT}"
|
||||
|
||||
log_note "creating local registry..."
|
||||
|
||||
# part of the configuration enabling kind access to a local running docker registry
|
||||
# this will eventually be replaced by a built-in kind feature:
|
||||
# - https://kind.sigs.k8s.io/docs/user/local-registry/
|
||||
# - https://github.com/kubernetes-sigs/kind/issues/1213
|
||||
reg_name='kind-registry'
|
||||
reg_port='5001'
|
||||
if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
|
||||
docker run \
|
||||
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --name "${reg_name}" \
|
||||
registry:2
|
||||
log_note "registry created..."
|
||||
fi
|
||||
|
||||
KIND_CLUSTER_NAME="pinniped"
|
||||
|
||||
log_note "creating kind cluster..."
|
||||
|
||||
# To choose a specific version of kube, add this option to the command below: `--image kindest/node:v1.28.0`.
|
||||
# To debug the kind config, add this option to the command below: `-v 10`
|
||||
kind create cluster --config "hack/lib/kind-config/single-node.yaml" --name pinniped
|
||||
kind create cluster --config "hack/lib/kind-config/single-node.yaml" --name "${KIND_CLUSTER_NAME}"
|
||||
|
||||
REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"
|
||||
for node in $(kind get nodes --name "${KIND_CLUSTER_NAME}"); do
|
||||
log_note "setting up node ${node} with registry....."
|
||||
docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
|
||||
cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
|
||||
[host."http://${reg_name}:5000"]
|
||||
EOF
|
||||
log_note "hosts.toml on node: ${node}....."
|
||||
docker exec "${node}" tail "${REGISTRY_DIR}/hosts.toml"
|
||||
done
|
||||
|
||||
if [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}' "${reg_name}")" = 'null' ]; then
|
||||
log_note "setting up docker network with kind..."
|
||||
docker network connect "kind" "${reg_name}"
|
||||
fi
|
||||
|
||||
log_note "documenting registry with configmap..."
|
||||
# 5. Document the local registry
|
||||
# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registry
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: local-registry-hosting
|
||||
namespace: kube-public
|
||||
data:
|
||||
localRegistryHosting.v1: |
|
||||
host: "localhost:${reg_port}"
|
||||
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
|
||||
EOF
|
||||
|
||||
kubectl get cm local-registry-hosting -n kube-public -o yaml
|
||||
|
||||
log_note "finished setting up kind cluster with local registry"
|
||||
|
@ -44,3 +44,11 @@ kubeadmConfigPatches:
|
||||
extraArgs:
|
||||
# See comment above.
|
||||
enable-aggregator-routing: "true"
|
||||
# part of the configuration enabling kind access to a local running docker registry
|
||||
# this will eventually be replaced by a built-in kind feature:
|
||||
# - https://kind.sigs.k8s.io/docs/user/local-registry/
|
||||
# - https://github.com/kubernetes-sigs/kind/issues/1213
|
||||
containerdConfigPatches:
|
||||
- |-
|
||||
[plugins."io.containerd.grpc.v1.cri".registry]
|
||||
config_path = "/etc/containerd/certs.d"
|
||||
|
@ -55,6 +55,7 @@ alternate_deploy="undefined"
|
||||
alternate_deploy_supervisor="undefined"
|
||||
alternate_deploy_concierge="undefined"
|
||||
alternate_deploy_local_user_authenticator="undefined"
|
||||
post_install="undefined"
|
||||
|
||||
# supported variable style:
|
||||
# --dockerfile-path ./foo.sh
|
||||
@ -140,6 +141,15 @@ while (("$#")); do
|
||||
alternate_deploy_local_user_authenticator=$1
|
||||
shift
|
||||
;;
|
||||
--post-install)
|
||||
shift
|
||||
if [[ "$#" == "0" || "$1" == -* ]]; then
|
||||
log_error "--post-install requires a script path to be specified"
|
||||
exit 1
|
||||
fi
|
||||
post_install=$1
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
log_error "Unsupported flag $1" >&2
|
||||
if [[ "$1" == *"active-directory"* ]]; then
|
||||
@ -169,6 +179,7 @@ if [[ "$help" == "yes" ]]; then
|
||||
log_note " -p, --alternate-deploy-supervisor: specify an alternate deploy script to install Pinniped Supervisor"
|
||||
log_note " -c, --alternate-deploy-concierge: specify an alternate deploy script to install Pinniped Concierge"
|
||||
log_note " -l, --alternate-deploy-local-user-authenticator: specify an alternate deploy script to install Pinniped local-user-authenticator"
|
||||
log_note " --post-install: specify an post-install script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -220,7 +231,8 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
registry="pinniped.local"
|
||||
# registry="pinniped.local"
|
||||
registry="localhost:5001" # local registry setup via splicing in https://kind.sigs.k8s.io/docs/user/local-registry/
|
||||
repo="test/build"
|
||||
registry_repo="$registry/$repo"
|
||||
tag=$(uuidgen) # always a new tag to force K8s to reload the image on redeploy
|
||||
@ -255,6 +267,9 @@ fi
|
||||
|
||||
# Load it into the cluster
|
||||
log_note "Loading the app's container image into the kind cluster..."
|
||||
# TODO: do I need to change anything here yet?
|
||||
# with this new update that we are making?
|
||||
# probably need to docker push to the new local registry instead of kind side-load?
|
||||
kind load docker-image "$registry_repo_tag" --name pinniped
|
||||
|
||||
#
|
||||
@ -402,6 +417,17 @@ fi
|
||||
#
|
||||
test_ca_bundle_pem="$(kubectl get secrets -n tools certs -o go-template='{{index .data "ca.pem"}}')"
|
||||
|
||||
|
||||
#
|
||||
# Call a post-install script
|
||||
# simplifies passing the $tag which may be necessary if the current local build is to be
|
||||
# referenced, for example, deploying via a Carvel package rather than our ytt mechanism
|
||||
if [ "$post_install" != "undefined" ] ; then
|
||||
log_note "The post-install script will be called with $tag..."
|
||||
$post_install post-install-script $tag
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# Create the environment file.
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user