Skip to content

Commit

Permalink
Salt: Add and Render Dex deployment configuration
Browse files Browse the repository at this point in the history
This commit adds the following:

Adds Dex Image to the buildchain

Adds method to obtain OIDC service IP and binds this
static IP as the ClusterIP address for Dex service

Adds `metalk8-auth` namespace which holds OIDC/authentication
cluster resources(PODS)

Automatically generate Dex deployment, service account,
cluster role and clusterrolebindings

The Dex chart.sls is generated from the Helm charts using:

```
$ ./charts/render.py dex metalk8s-auth charts/dex.yaml charts/dex/ >
salt/metalk8s/addons/dex/deployed/chart.sls

Add states to deploy Dex and related server certificates

Closes: #2007
Closes: #2011
  • Loading branch information
Ebaneck authored and ChengYanJin committed Dec 17, 2019
1 parent 92b7d66 commit 344c329
Show file tree
Hide file tree
Showing 21 changed files with 583 additions and 0 deletions.
1 change: 1 addition & 0 deletions buildchain/buildchain/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# URLs of the main container repositories.
CALICO_REPOSITORY : str = 'quay.io/calico'
COREOS_REPOSITORY : str = 'quay.io/coreos'
DEX_REPOSITORY : str = 'quay.io/dexidp'
DOCKER_REPOSITORY : str = 'docker.io/library'
GOOGLE_REPOSITORY : str = 'k8s.gcr.io'
GRAFANA_REPOSITORY : str = 'docker.io/grafana'
Expand Down
3 changes: 3 additions & 0 deletions buildchain/buildchain/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ def _operator_image(name: str, **kwargs: Any) -> targets.OperatorImage:
'prometheus-config-reloader',
'prometheus-operator',
],
constants.DEX_REPOSITORY: [
'dex',
],
constants.DOCKER_REPOSITORY: [
'nginx',
],
Expand Down
10 changes: 10 additions & 0 deletions buildchain/buildchain/salt_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,16 @@ def _get_parts(self) -> Iterator[str]:
renderer=targets.Renderer.JSON,
),

Path('salt/metalk8s/addons/dex/ca/init.sls'),
Path('salt/metalk8s/addons/dex/ca/installed.sls'),
Path('salt/metalk8s/addons/dex/ca/advertised.sls'),
Path('salt/metalk8s/addons/dex/certs/init.sls'),
Path('salt/metalk8s/addons/dex/certs/server.sls'),
Path('salt/metalk8s/addons/dex/deployed/chart.sls'),
Path('salt/metalk8s/addons/dex/deployed/init.sls'),
Path('salt/metalk8s/addons/dex/deployed/namespace.sls'),
Path('salt/metalk8s/addons/dex/deployed/tls-secret.sls'),

Path('salt/metalk8s/addons/prometheus-operator/deployed/chart.sls'),
Path('salt/metalk8s/addons/prometheus-operator/deployed/cleanup.sls'),
Path('salt/metalk8s/addons/prometheus-operator/deployed/dashboards.sls'),
Expand Down
5 changes: 5 additions & 0 deletions buildchain/buildchain/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ def _version_prefix(version: str, prefix: str = 'v') -> str:
version='1.3.1',
digest='sha256:02382353821b12c21b062c59184e227e001079bb13ebd01f9d3270ba0fcbf1e4',
),
Image(
name='dex',
version='v2.19.0',
digest='sha256:132523cc3e9402a5e12c3b7d837da6f0c96d8a05f27bf6ba42458c2a0d1c01f5',
),
Image(
name='etcd',
version='3.3.15-0',
Expand Down
94 changes: 94 additions & 0 deletions charts/dex.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
image: '{% endraw %}{{ build_image_name(\"dex\", False) }}{% raw %}'

nodeSelector:
node-role.kubernetes.io/infra: ''

tolerations:
- key: "node-role.kubernetes.io/bootstrap"
operator: "Exists"
effect: "NoSchedule"
- key: "node-role.kubernetes.io/infra"
operator: "Exists"
effect: "NoSchedule"

replicas: 2

# grpc support
grpc: false

# https termination by dex itself
https: true

service:
clusterIP: '{% endraw %}{{ salt.metalk8s_network.get_oidc_service_ip() }}{% raw %}'

ingress:
enabled: true
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
kubernetes.io/ingress.class: "nginx-control-plane"
path: /oidc
hosts:
- null

# extraVolumes:
# - name: theme
# configMap:
# name: dex-branding

# extraVolumeMounts:
# - name: theme
# mountPath: /web/themes/custom/

certs:
web:
create: false
grpc:
create: false

config:
issuer: '{% endraw %}https://{{ grains.metalk8s.control_plane_ip }}:8443/oidc{% raw %}'
web:
tlsCert: /etc/dex/tls/https/server/tls.crt
tlsKey: /etc/dex/tls/https/server/tls.key
frontend:
theme: "coreos" #metalk8s-ui
# dir: /web/themes/custom/

connectors: {}

oauth2:
alwaysShowLoginScreen: true
skipApprovalScreen: true
responseTypes: ["code", "token", "id_token"]

expiry:
signingKeys: "6h"
idTokens: "24h"

staticClients:
- id: oidc-auth-client
redirectURIs:
- 'urn:ietf:wg:oauth:2.0:oob'
name: 'oidc-auth-client'
secret: "lkfa9jaf3kfakqyeoikfjakf93k2l"
trustedPeers:
- metalk8s-ui
- grafana-ui
- id: metalk8s-ui
redirectURIs:
- '{% endraw %}https://{{ grains.metalk8s.control_plane_ip }}:8443/oauth2/callback{% raw %}'
name: 'MetalK8s UI'
secret: "ybrMJpVMQxsiZw26MhJzCjA2ut"
- id: grafana-ui
name: 'Grafana UI'
redirectURIs:
- '{% endraw %}https://{{ grains.metalk8s.control_plane_ip }}:8443/grafana/login/generic_oauth{% raw %}'
secret: "4lqK98NcsWG5qBRHJUqYM1"

staticPasswords:
- email: "[email protected]"
# bcrypt hash of the string "password"
hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
username: "admin"
userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"
11 changes: 11 additions & 0 deletions pillar/metalk8s/roles/ca.sls
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ mine_functions:
mine_function: hashutil.base64_encodefile
fname: /etc/kubernetes/pki/sa.pub

dex_ca_b64:
mine_function: hashutil.base64_encodefile
fname: /etc/metalk8s/pki/dex/ca.crt

ingress_ca_b64:
mine_function: hashutil.base64_encodefile
fname: /etc/metalk8s/pki/nginx-ingress/ca.crt
Expand Down Expand Up @@ -62,3 +66,10 @@ x509_signing_policies:
- keyUsage: critical digitalSignature, keyEncipherment
- extendedKeyUsage: serverAuth
- days_valid: 365
dex_server_policy:
- minions: '*'
- signing_private_key: /etc/metalk8s/pki/dex/ca.key
- signing_cert: /etc/metalk8s/pki/dex/ca.crt
- keyUsage: critical digitalSignature, keyEncipherment
- extendedKeyUsage: serverAuth
- days_valid: 365
11 changes: 11 additions & 0 deletions salt/_modules/metalk8s_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from salt.exceptions import CommandExecutionError

K8S_CLUSTER_ADDRESS_NUMBER = 0
OIDC_ADDRESS_NUMBER = 6
COREDNS_ADDRESS_NUMBER = 9


Expand Down Expand Up @@ -68,3 +69,13 @@ def get_cluster_dns_ip():
range.
'''
return _pick_nth_service_ip(COREDNS_ADDRESS_NUMBER)


def get_oidc_service_ip():
'''
Return the OIDC service cluster IP.
This IP is arbitrarily selected as the seventh IP from the usable hosts
range.
'''
return _pick_nth_service_ip(OIDC_ADDRESS_NUMBER)
25 changes: 25 additions & 0 deletions salt/metalk8s/addons/dex/ca/advertised.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{%- set dex_ca_b64_server = salt['mine.get'](
pillar.metalk8s.ca.minion, 'dex_ca_b64'
) %}

{%- if dex_ca_b64_server %}

{%- set dex_cert_b64 = dex_ca_b64_server[pillar.metalk8s.ca.minion] %}
{%- set dex_ca_cert = salt['hashutil.base64_b64decode'](dex_cert_b64) %}

Ensure Dex CA cert is present:
file.managed:
- name: /etc/metalk8s/pki/dex/ca.crt
- user: root
- group : root
- mode: 644
- makedirs: True
- dir_mode: 755
- contents: {{ dex_ca_cert.splitlines() }}

{%- else %}

Unable to get Dex CA cert, no kubernetes_dex_ca_b64 in mine:
test.fail_without_changes: []

{%- endif %}
11 changes: 11 additions & 0 deletions salt/metalk8s/addons/dex/ca/init.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#
# State to manage Dex Certificate Authority
#
# Available states
# ================
#
# * installed -> install and advertise as Dex CA
# * advertised -> deploy the Dex CA certificate
#
include:
- .installed
42 changes: 42 additions & 0 deletions salt/metalk8s/addons/dex/ca/installed.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{%- from "metalk8s/map.jinja" import dex with context %}
include:
- metalk8s.internal.m2crypto
Create dex CA private key:
x509.private_key_managed:
- name: /etc/metalk8s/pki/dex/ca.key
- bits: 4096
- verbose: False
- user: root
- group: root
- mode: 600
- makedirs: True
- dir_mode: 755
- require:
- metalk8s_package_manager: Install m2crypto
Generate dex CA certificate:
x509.certificate_managed:
- name: /etc/metalk8s/pki/dex/ca.crt
- signing_private_key: /etc/metalk8s/pki/dex/ca.key
- CN: dex-ca
- keyUsage: "critical digitalSignature, keyEncipherment, keyCertSign"
- basicConstraints: "critical CA:true"
- days_valid: {{ dex.ca.cert.days_valid }}
- user: root
- group: root
- mode: 644
- makedirs: True
- dir_mode: 755
- require:
- x509: Create dex CA private key
Advertise dex CA certificate in the mine:
module.wait:
- mine.send:
- func: dex_ca_b64
- mine_function: hashutil.base64_encodefile
- /etc/metalk8s/pki/dex/ca.crt
- watch:
- x509: Generate dex CA certificate
2 changes: 2 additions & 0 deletions salt/metalk8s/addons/dex/certs/init.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include:
- .server
47 changes: 47 additions & 0 deletions salt/metalk8s/addons/dex/certs/server.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{%- from "metalk8s/map.jinja" import dex with context %}
{%- set oidc_service_ip = salt.metalk8s_network.get_oidc_service_ip() %}
include:
- metalk8s.internal.m2crypto
Create Dex server private key:
x509.private_key_managed:
- name: /etc/metalk8s/pki/dex/server.key
- bits: 4096
- verbose: False
- user: root
- group: root
- mode: 600
- makedirs: True
- dir_mode: 755
- require:
- metalk8s_package_manager: Install m2crypto
{%- set certSANs = [
grains.fqdn,
'localhost',
'127.0.0.1',
'dex',
'dex.metalk8s-auth',
'dex.metalk8s-auth.svc',
'dex.metalk8s-auth.svc.cluster.local',
oidc_service_ip,
grains.metalk8s.control_plane_ip,
] %}
Generate Dex server certificate:
x509.certificate_managed:
- name: /etc/metalk8s/pki/dex/server.crt
- public_key: /etc/metalk8s/pki/dex/server.key
- ca_server: {{ pillar.metalk8s.ca.minion }}
- signing_policy: {{ dex.cert.server_signing_policy }}
- CN: dex-server
- subjectAltName: "{{ salt['metalk8s.format_san'](certSANs | unique) }}"
- user: root
- group: root
- mode: 644
- makedirs: True
- dir_mode: 755
- require:
- x509: Create Dex server private key
Loading

0 comments on commit 344c329

Please sign in to comment.