diff --git a/README.md b/README.md index 34a3cc8b0..3634a67d3 100644 --- a/README.md +++ b/README.md @@ -59,4 +59,7 @@ kubectl apply -k components/01-secrets/ kubectl -n argocd apply -k apps/components/ ``` -ArgoCD should successfully get everything deployed. +ArgoCD should successfully get Nautobot deployed. Now come the OpenStack +components which aren't working with GitOps methods at this time. + +[Install Keystone](./components/10-keystone/README.md) diff --git a/apps/components/keystone.yaml b/apps/components/keystone.yaml new file mode 100644 index 000000000..f87b2d3e9 --- /dev/null +++ b/apps/components/keystone.yaml @@ -0,0 +1,16 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: keystone +spec: + project: understack + source: + repoURL: https://github.com/rackerlabs/understack.git + path: components/10-keystone/ + targetRevision: HEAD + destination: + server: "https://kubernetes.default.svc" + namespace: openstack + syncPolicy: + automated: + selfHeal: true diff --git a/apps/components/kustomization.yaml b/apps/components/kustomization.yaml index 7c765a4d3..413c01e99 100644 --- a/apps/components/kustomization.yaml +++ b/apps/components/kustomization.yaml @@ -11,3 +11,4 @@ resources: - memcached.yaml - postgres-db.yaml - nautobot.yaml + - keystone.yaml diff --git a/components/01-secrets/README.md b/components/01-secrets/README.md index 85ca1ce8e..58eb7ff34 100644 --- a/components/01-secrets/README.md +++ b/components/01-secrets/README.md @@ -81,6 +81,48 @@ kubeseal \ -w components/01-secrets/encrypted-nautobot-redis.yaml ``` +## Keystone + +Generate the necessary secrets for OpenStack Keystone. + +```bash +kubectl --namespace openstack \ + create secret generic keystone-rabbitmq-password \ + --type Opaque \ + --from-literal=username="keystone" \ + --from-literal=password="$($(git rev-parse --show-toplevel)/scripts/pwgen.sh)" \ + --dry-run -o yaml > secret-keystone-rabbitmq-password.yaml +kubectl --namespace openstack \ + create secret generic keystone-db-password \ + --type Opaque \ + --from-literal=password="$($(git rev-parse --show-toplevel)/scripts/pwgen.sh)" \ + --dry-run -o yaml > secret-keystone-db-password.yaml +kubectl --namespace openstack \ + create secret generic keystone-admin \ + --type Opaque \ + --from-literal=password="$($(git rev-parse --show-toplevel)/scripts/pwgen.sh)" \ + --dry-run -o yaml > secret-keystone-admin.yaml +kubectl --namespace openstack \ + create secret generic keystone-credential-keys \ + --type Opaque \ + --from-literal=password="$($(git rev-parse --show-toplevel)/scripts/pwgen.sh)" \ + --dry-run -o yaml > secret-keystone-credential-keys.yaml +``` + +Now let's seal them. + +```bash +for skrt in $(find . -name "secret-keystone*.yaml" -depth 1); do + encskrt=$(echo "${skrt}" | sed -e 's/secret-/components\/01-secrets\/encrypted-/') + kubeseal \ + --scope cluster-wide \ + --allow-empty-data \ + -o yaml \ + -f "${skrt}" \ + -w "${encskrt}" +done +``` + ## Generate Kustomize for the Install Now generate the kustomize for this. diff --git a/components/03-mariadb/kustomization.yaml b/components/03-mariadb/kustomization.yaml index 416b78a7e..5456466cb 100644 --- a/components/03-mariadb/kustomization.yaml +++ b/components/03-mariadb/kustomization.yaml @@ -1,6 +1,7 @@ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization + resources: - mariadb-configmap.yaml - mariadb-instance.yaml diff --git a/components/10-keystone/README.md b/components/10-keystone/README.md new file mode 100644 index 000000000..c4b5774c8 --- /dev/null +++ b/components/10-keystone/README.md @@ -0,0 +1,52 @@ +# OpenStack Keystone + +So unfortunately OpenStack Helm doesn't publish helm charts that can be consumed like +regular helm charts. You must instead clone two of their git repos side by side and +build the dependencies manually. They additionally don't split out secrets but instead +template them into giant config files or even executable scripts that then get stored +as secrets, a clear violation of . As a result we cannot store +a declarative config of Keystone and allow users to supply their own secrets. + +Due to the above issues, for now we'll skip the ArgoCD ability for this deployment. + +## Get OpenStack Helm Ready + +You may have done this for another OpenStack component and can share the same +git clones. This assumes you're doing this from the top level of this repo. + +```bash +# clone the two repos because they reference the infra one as a relative path +# so you can't use real helm commands +git clone https://github.com/openstack/openstack-helm +git clone https://github.com/openstack/openstack-helm-infra +# update the dependencies cause we can't use real helm references +./scripts/openstack-helm-depend-sync.sh keystone +cd components/10-keystone +``` + +## Deploy Keystone + +Since we cannot refer to the secrets by name, we must look them up live from the cluster +so that we can injected them into the templated configs. Upstream should really allow +secrets to be passed by reference. As a result of this we cannot use GitOps to generate +these charts and have them applied to the cluster. + +Secrets Reference: + +- openstack-default-user is created by the messaging-topology-operator which is + executed by the rabbitmq-queues component. The name stems from the RabbitMQ + cluster from the rabbitmq-cluster component. `${CLUSTER_NAME}-default-user` + +```bash +helm --namespace openstack template \ + keystone \ + ./openstack-helm/keystone/ \ + -f aio-values.yaml \ + --set endpoints.identity.auth.admin.password="$(kubectl --namespace openstack get secret keystone-admin -o jsonpath='{.data.password}' | base64 -d)" \ + --set endpoints.oslo_db.auth.admin.password="$(kubectl --namespace openstack get secret mariadb -o jsonpath='{.data.root-password}' | base64 -d)" \ + --set endpoints.oslo_db.auth.keystone.password="$(kubectl --namespace openstack get secret keystone-db-password -o jsonpath='{.data.password}' | base64 -d)" \ + --set endpoints.oslo_messaging.auth.admin.password="$(kubectl --namespace openstack get secret openstack-default-user -o jsonpath='{.data.password}' | base64 -d)" \ + --set endpoints.oslo_messaging.auth.keystone.password="$(kubectl --namespace openstack get secret keystone-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)" \ + --post-renderer $(git rev-parse --show-toplevel)/scripts/openstack-helm-sealed-secrets.sh \ + | kubectl -n openstack apply -f - +``` diff --git a/components/10-keystone/aio-values.yaml b/components/10-keystone/aio-values.yaml new file mode 100644 index 000000000..0d526698a --- /dev/null +++ b/components/10-keystone/aio-values.yaml @@ -0,0 +1,1105 @@ +--- +labels: + api: + node_selector_key: openstack-control-plane + node_selector_value: enabled + job: + node_selector_key: openstack-control-plane + node_selector_value: enabled + test: + node_selector_key: openstack-control-plane + node_selector_value: enabled + +release_group: null + +# NOTE(gagehugo): the pre-install hook breaks upgrade for helm2 +# Set to false to upgrade using helm2 +helm3_hook: true + +images: + tags: + bootstrap: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy" + db_init: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy" + db_drop: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy" + keystone_api: "ghcr.io/rackerlabs/genestack/keystone-rxt:2023.1-ubuntu_jammy" + keystone_bootstrap: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy" + keystone_credential_rotate: "ghcr.io/rackerlabs/genestack/keystone-rxt:2023.1-ubuntu_jammy" + keystone_credential_setup: "ghcr.io/rackerlabs/genestack/keystone-rxt:2023.1-ubuntu_jammy" + keystone_db_sync: "ghcr.io/rackerlabs/genestack/keystone-rxt:2023.1-ubuntu_jammy" + keystone_domain_manage: "ghcr.io/rackerlabs/genestack/keystone-rxt:2023.1-ubuntu_jammy" + keystone_fernet_rotate: "ghcr.io/rackerlabs/genestack/keystone-rxt:2023.1-ubuntu_jammy" + keystone_fernet_setup: "ghcr.io/rackerlabs/genestack/keystone-rxt:2023.1-ubuntu_jammy" + ks_user: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy" + test: docker.io/xrally/xrally-openstack:2.0.0 + rabbit_init: docker.io/rabbitmq:3.7-management + keystone_credential_cleanup: "docker.io/openstackhelm/heat:2023.1-ubuntu_jammy" + dep_check: quay.io/airshipit/kubernetes-entrypoint:v1.0.0 + image_repo_sync: docker.io/docker:17.07.0 + pull_policy: "IfNotPresent" + local_registry: + active: false + exclude: + - dep_check + - image_repo_sync + +bootstrap: + enabled: true + ks_user: admin + script: | + # admin needs the admin role for the default domain + openstack role add \ + --user="${OS_USERNAME}" \ + --domain="${OS_DEFAULT_DOMAIN}" \ + "admin" + +network: + api: + ingress: + public: true + classes: + namespace: "nginx" + cluster: "nginx-openstack" + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + external_policy_local: false + node_port: + enabled: false + port: 30500 + admin: + node_port: + enabled: false + port: 30357 + +dependencies: + dynamic: + common: + local_image_registry: + jobs: + - keystone-image-repo-sync + services: + - endpoint: node + service: local_image_registry + rabbit_init: + services: + - service: oslo_messaging + endpoint: internal + static: + api: + jobs: + - keystone-db-sync + - keystone-credential-setup + - keystone-fernet-setup + services: + - endpoint: internal + service: oslo_cache + - endpoint: internal + service: oslo_db + bootstrap: + jobs: + - keystone-domain-manage + services: + - endpoint: internal + service: identity + credential_rotate: + jobs: + - keystone-credential-setup + credential_setup: null + credential_cleanup: + services: + - endpoint: internal + service: oslo_db + db_drop: + services: + - endpoint: internal + service: oslo_db + db_init: + services: + - endpoint: internal + service: oslo_db + db_sync: + jobs: + # - keystone-db-init + - keystone-credential-setup + - keystone-fernet-setup + services: + - endpoint: internal + service: oslo_db + domain_manage: + services: + - endpoint: internal + service: identity + fernet_rotate: + jobs: + - keystone-fernet-setup + fernet_setup: null + tests: + services: + - endpoint: internal + service: identity + image_repo_sync: + services: + - endpoint: internal + service: local_image_registry + +pod: + security_context: + keystone: + pod: + runAsUser: 42424 + container: + keystone_api: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + credential_setup: + pod: + runAsUser: 42424 + container: + keystone_credential_setup: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + fernet_setup: + pod: + runAsUser: 42424 + container: + keystone_fernet_setup: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + fernet_rotate: + pod: + runAsUser: 42424 + container: + keystone_fernet_rotate: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + domain_manage: + pod: + runAsUser: 42424 + container: + keystone_domain_manage_init: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + keystone_domain_manage: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + test: + pod: + runAsUser: 42424 + container: + keystone_test_ks_user: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + keystone_test: + runAsUser: 65500 + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + affinity: + anti: + type: + default: preferredDuringSchedulingIgnoredDuringExecution + topologyKey: + default: kubernetes.io/hostname + weight: + default: 10 + tolerations: + keystone: + enabled: false + tolerations: + - key: node-role.kubernetes.io/master + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/control-plane + operator: Exists + effect: NoSchedule + mounts: + keystone_db_init: + init_container: null + keystone_db_init: + volumeMounts: + volumes: + keystone_db_sync: + init_container: null + keystone_db_sync: + volumeMounts: + volumes: + keystone_api: + init_container: null + keystone_api: + volumeMounts: + volumes: + keystone_tests: + init_container: null + keystone_tests: + volumeMounts: + volumes: + keystone_bootstrap: + init_container: null + keystone_bootstrap: + volumeMounts: + volumes: + keystone_fernet_setup: + init_container: null + keystone_fernet_setup: + volumeMounts: + volumes: + keystone_fernet_rotate: + init_container: null + keystone_fernet_rotate: + volumeMounts: + volumes: + keystone_credential_setup: + init_container: null + keystone_credential_setup: + volumeMounts: + volumes: + keystone_credential_rotate: + init_container: null + keystone_credential_rotate: + volumeMounts: + volumes: + keystone_credential_cleanup: + init_container: null + keystone_credential_cleanup: + volumeMounts: + volumes: + keystone_domain_manage: + init_container: null + keystone_domain_manage: + volumeMounts: + volumes: + replicas: + api: 1 + lifecycle: + upgrades: + deployments: + revision_history: 3 + pod_replacement_strategy: RollingUpdate + rolling_update: + max_unavailable: 1 + max_surge: 3 + disruption_budget: + api: + min_available: 0 + termination_grace_period: + api: + timeout: 30 + resources: + enabled: false + api: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + jobs: + bootstrap: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + domain_manage: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + db_init: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + db_sync: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + db_drop: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + rabbit_init: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + tests: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + fernet_setup: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + fernet_rotate: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + credential_setup: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + credential_rotate: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + credential_cleanup: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + image_repo_sync: + requests: + memory: "64Mi" + cpu: "100m" + limits: + memory: "4096Mi" + probes: + api: + api: + readiness: + enabled: true + params: + initialDelaySeconds: 15 + periodSeconds: 60 + timeoutSeconds: 15 + liveness: + enabled: true + params: + initialDelaySeconds: 50 + periodSeconds: 60 + timeoutSeconds: 15 +jobs: + fernet_setup: + user: keystone + group: keystone + fernet_rotate: + # NOTE(rk760n): key rotation frequency, token expiration, active keys should statisfy the formula + # max_active_keys = (token_expiration / rotation_frequency) + 2 + # as expiration is 12h, and max_active_keys set to 3 by default, rotation_frequency need to be adjusted + # 12 hours + cron: "0 */12 * * *" + user: keystone + group: keystone + history: + success: 3 + failed: 1 + credential_setup: + user: keystone + group: keystone + credential_rotate: + # monthly + cron: "0 0 1 * *" + migrate_wait: 120 + user: keystone + group: keystone + history: + success: 3 + failed: 1 + +network_policy: + keystone: + ingress: + - {} + egress: + - {} + +conf: + security: | + # + # Disable access to the entire file system except for the directories that + # are explicitly allowed later. + # + # This currently breaks the configurations that come with some web application + # Debian packages. + # + # + # AllowOverride None + # Require all denied + # + + # Changing the following options will not really affect the security of the + # server, but might make attacks slightly more difficult in some cases. + + # + # ServerTokens + # This directive configures what you return as the Server HTTP response + # Header. The default is 'Full' which sends information about the OS-Type + # and compiled in modules. + # Set to one of: Full | OS | Minimal | Minor | Major | Prod + # where Full conveys the most information, and Prod the least. + ServerTokens Prod + + # + # Optionally add a line containing the server version and virtual host + # name to server-generated pages (internal error documents, FTP directory + # listings, mod_status and mod_info output etc., but not CGI generated + # documents or custom error documents). + # Set to "EMail" to also include a mailto: link to the ServerAdmin. + # Set to one of: On | Off | EMail + ServerSignature Off + + # + # Allow TRACE method + # + # Set to "extended" to also reflect the request body (only for testing and + # diagnostic purposes). + # + # Set to one of: On | Off | extended + TraceEnable Off + + # + # Forbid access to version control directories + # + # If you use version control systems in your document root, you should + # probably deny access to their directories. For example, for subversion: + # + # + # Require all denied + # + + # + # Setting this header will prevent MSIE from interpreting files as something + # else than declared by the content type in the HTTP headers. + # Requires mod_headers to be enabled. + # + #Header set X-Content-Type-Options: "nosniff" + + # + # Setting this header will prevent other sites from embedding pages from this + # site as frames. This defends against clickjacking attacks. + # Requires mod_headers to be enabled. + # + #Header set X-Frame-Options: "sameorigin" + software: + apache2: + binary: apache2 + start_parameters: -DFOREGROUND + site_dir: /etc/apache2/sites-enable + conf_dir: /etc/apache2/conf-enabled + mods_dir: /etc/apache2/mods-available + a2enmod: null + a2dismod: null + keystone: + DEFAULT: + log_config_append: /etc/keystone/logging.conf + max_token_size: 255 + # NOTE(rk760n): if you need auth notifications to be sent, uncomment it + # notification_opt_out: "" + token: + provider: fernet + # 12 hours + expiration: 43200 + identity: + domain_specific_drivers_enabled: True + domain_config_dir: /etc/keystone/domains + fernet_tokens: + key_repository: /etc/keystone/fernet-keys/ + credential: + key_repository: /etc/keystone/credential-keys/ + database: + max_retries: -1 + cache: + enabled: true + backend: dogpile.cache.memcached + oslo_messaging_notifications: + driver: messagingv2 + oslo_messaging_rabbit: + rabbit_ha_queues: true + oslo_middleware: + enable_proxy_headers_parsing: true + oslo_policy: + policy_file: /etc/keystone/policy.yaml + security_compliance: + # NOTE(vdrok): The following two options have effect only for SQL backend + lockout_failure_attempts: 5 + lockout_duration: 1800 + auth: + methods: password,token,application_credential,totp + password: rxt + totp: rxt + + # NOTE(lamt) We can leverage multiple domains with different + # configurations as outlined in + # https://docs.openstack.org/keystone/pike/admin/identity-domain-specific-config.html. + # A sample of the value override can be found in sample file: + # tools/overrides/example/keystone_domain_config.yaml + # ks_domains: + policy: {} + access_rules: {} + rabbitmq: + # NOTE(rk760n): adding rmq policy to mirror messages from notification queues and set expiration time for the ones + policies: + - vhost: "keystone" + name: "ha_ttl_keystone" + definition: + # mirror messges to other nodes in rmq cluster + ha-mode: "all" + ha-sync-mode: "automatic" + # 70s + message-ttl: 70000 + priority: 0 + apply-to: all + pattern: '^(?!(amq\.|reply_)).*' + rally_tests: + run_tempest: false + tests: + KeystoneBasic.add_and_remove_user_role: + - runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.authenticate_user_and_validate_token: + - args: {} + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_add_and_list_user_roles: + - runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_and_delete_ec2credential: + - runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_and_list_ec2credentials: + - runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_and_delete_role: + - runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_and_delete_service: + - args: + description: test_description + service_type: Rally_test_type + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_and_get_role: + - args: {} + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_and_list_services: + - args: + description: test_description + service_type: Rally_test_type + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_and_list_tenants: + - args: {} + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_and_list_users: + - args: {} + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_delete_user: + - args: {} + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_tenant: + - args: {} + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_tenant_with_users: + - args: + users_per_tenant: 1 + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_update_and_delete_tenant: + - args: {} + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_user: + - args: {} + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_user_set_enabled_and_delete: + - args: + enabled: true + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + - args: + enabled: false + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.create_user_update_password: + - args: {} + runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + KeystoneBasic.get_entities: + - runner: + concurrency: 1 + times: 1 + type: constant + sla: + failure_rate: + max: 0 + mpm_event: | + + ServerLimit 1024 + StartServers 32 + MinSpareThreads 32 + MaxSpareThreads 256 + ThreadsPerChild 25 + MaxRequestsPerChild 128 + ThreadLimit 720 + + wsgi_keystone: | + {{- $portInt := tuple "identity" "service" "api" $ | include "helm-toolkit.endpoints.endpoint_port_lookup" }} + + Listen 0.0.0.0:{{ $portInt }} + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" proxy + + SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded + CustomLog /dev/stdout combined env=!forwarded + CustomLog /dev/stdout proxy env=forwarded + + + WSGIDaemonProcess keystone-public processes=1 threads=1 user=keystone group=keystone display-name=%{GROUP} + WSGIProcessGroup keystone-public + WSGIScriptAlias / /var/www/cgi-bin/keystone/keystone-wsgi-public + WSGIApplicationGroup %{GLOBAL} + WSGIPassAuthorization On + = 2.4> + ErrorLogFormat "%{cu}t %M" + + ErrorLog /dev/stdout + + SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded + CustomLog /dev/stdout combined env=!forwarded + CustomLog /dev/stdout proxy env=forwarded + + sso_callback_template: | + + + + Keystone WebSSO redirect + + +
+ Please wait... +
+ + +
+ + + + logging: + loggers: + keys: + - root + - keystone + handlers: + keys: + - stdout + - stderr + - "null" + formatters: + keys: + - context + - default + logger_root: + level: WARNING + handlers: 'null' + logger_keystone: + level: INFO + handlers: + - stdout + qualname: keystone + logger_amqp: + level: WARNING + handlers: stderr + qualname: amqp + logger_amqplib: + level: WARNING + handlers: stderr + qualname: amqplib + logger_eventletwsgi: + level: WARNING + handlers: stderr + qualname: eventlet.wsgi.server + logger_sqlalchemy: + level: WARNING + handlers: stderr + qualname: sqlalchemy + logger_boto: + level: WARNING + handlers: stderr + qualname: boto + handler_null: + class: logging.NullHandler + formatter: default + args: () + handler_stdout: + class: StreamHandler + args: (sys.stdout,) + formatter: context + handler_stderr: + class: StreamHandler + args: (sys.stderr,) + formatter: context + formatter_context: + class: oslo_log.formatters.ContextFormatter + datefmt: "%Y-%m-%d %H:%M:%S" + formatter_default: + format: "%(message)s" + datefmt: "%Y-%m-%d %H:%M:%S" + +# Names of secrets used by bootstrap and environmental checks +secrets: + identity: + admin: keystone-keystone-admin + test: keystone-keystone-test + oslo_db: + admin: keystone-db-admin + keystone: keystone-db-user + oslo_messaging: + admin: keystone-rabbitmq-admin + keystone: keystone-rabbitmq-user + ldap: + tls: keystone-ldap-tls + tls: + identity: + api: + public: keystone-tls-public + internal: keystone-tls-public + oci_image_registry: + keystone: keystone-oci-image-registry + +# typically overridden by environmental +# values, but should include all endpoints +# required by this chart +endpoints: + cluster_domain_suffix: cluster.local + local_image_registry: + name: docker-registry + namespace: docker-registry + hosts: + default: localhost + internal: docker-registry + node: localhost + host_fqdn_override: + default: null + port: + registry: + node: 5000 + oci_image_registry: + name: oci-image-registry + namespace: oci-image-registry + auth: + enabled: false + keystone: + username: keystone + password: password + hosts: + default: localhost + host_fqdn_override: + default: null + port: + registry: + default: null + identity: + namespace: null + name: keystone + auth: + admin: + region_name: RegionOne + username: admin + password: password + project_name: admin + user_domain_name: default + project_domain_name: default + default_domain_id: default + # test: + # role: admin + # region_name: RegionOne + # username: keystone-test + # password: password + # project_name: test + # user_domain_name: default + # project_domain_name: default + # default_domain_id: default + hosts: + default: keystone + internal: keystone-api + host_fqdn_override: + default: null + # NOTE(portdirect): this chart supports TLS for fqdn over-ridden public + # endpoints using the following format: + # public: + # host: null + # tls: + # crt: null + # key: null + path: + default: /v3 + scheme: + default: http + service: http + port: + api: + admin: 5000 + default: 80 + # NOTE(portdirect): to retain portability across images, and allow + # running under a unprivileged user simply, we default to a port > 1000. + internal: 5000 + service: 5000 + oslo_db: + namespace: null + auth: + admin: + username: root + password: password + secret: + tls: + internal: mariadb-tls-direct + keystone: + username: keystone + password: password + hosts: + default: mariadb + host_fqdn_override: + default: null + path: /keystone + scheme: mysql+pymysql + port: + mysql: + default: 3306 + oslo_messaging: + namespace: null + auth: + admin: + username: rabbitmq + password: password + secret: + tls: + internal: rabbitmq-tls-direct + keystone: + username: keystone + password: password + statefulset: + replicas: 3 + name: rabbitmq-server + hosts: + default: rabbitmq-nodes + host_fqdn_override: + default: null + path: /keystone + scheme: rabbit + port: + amqp: + default: 5672 + http: + default: 15672 + oslo_cache: + namespace: null + hosts: + default: memcached + host_fqdn_override: + default: null + port: + memcache: + default: 11211 + ldap: + auth: + client: + tls: + # NOTE(lamt): Specify a CA value here will place a LDAPS certificate at + # /etc/certs/tls.ca. To ensure keystone uses LDAPS, the + # following key will need to be overrided under section [ldap] or the + # correct domain-specific setting, else it will not be enabled: + # + # use_tls: true + # tls_req_cert: allow # Valid values: demand, never, allow + # tls_cacertfile: /etc/certs/tls.ca # abs path to the CA cert + ca: null + fluentd: + namespace: null + name: fluentd + hosts: + default: fluentd-logging + host_fqdn_override: + default: null + path: + default: null + scheme: 'http' + port: + service: + default: 24224 + metrics: + default: 24220 + # NOTE(tp6510): these endpoints allow for things like DNS lookups and ingress + # They are using to enable the Egress K8s network policy. + kube_dns: + namespace: kube-system + name: kubernetes-dns + hosts: + default: kube-dns + host_fqdn_override: + default: null + path: + default: null + scheme: http + port: + dns: + default: 53 + protocol: UDP + ingress: + namespace: null + name: ingress + hosts: + default: ingress + port: + ingress: + default: 80 + +tls: + identity: false + oslo_messaging: false + oslo_db: false + +manifests: + certificates: false + configmap_bin: true + configmap_etc: true + cron_credential_rotate: true + cron_fernet_rotate: true + deployment_api: true + ingress_api: true + job_bootstrap: true + job_credential_cleanup: false + job_credential_setup: true + job_db_init: false + job_db_sync: true + job_db_drop: false + job_domain_manage: true + job_fernet_setup: true + job_image_repo_sync: true + job_rabbit_init: false + pdb_api: true + pod_rally_test: false + network_policy: false + secret_credential_keys: true + secret_db: true + secret_fernet_keys: true + secret_ingress_tls: true + secret_keystone: true + secret_rabbitmq: true + secret_registry: true + service_ingress_api: true + service_api: true diff --git a/components/10-keystone/keystone-mariadb-db.yaml b/components/10-keystone/keystone-mariadb-db.yaml new file mode 100644 index 000000000..be0499aef --- /dev/null +++ b/components/10-keystone/keystone-mariadb-db.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: mariadb.mmontes.io/v1alpha1 +kind: Database +metadata: + name: keystone + namespace: openstack +spec: + # If you want the database to be created with a different name than the resource name + # name: data-custom + mariaDbRef: + name: mariadb # name of the MariaDB kind + waitForIt: true + characterSet: utf8 + collate: utf8_general_ci + retryInterval: 5s +--- +apiVersion: mariadb.mmontes.io/v1alpha1 +kind: User +metadata: + name: keystone + namespace: openstack +spec: + # If you want the user to be created with a different name than the resource name + # name: user-custom + mariaDbRef: + name: mariadb # name of the MariaDB kind + waitForIt: true + passwordSecretKeyRef: + name: keystone-db-password + key: password + # This field is immutable and defaults to 10, 0 means unlimited. + maxUserConnections: 0 + host: "%" + retryInterval: 5s +--- +apiVersion: mariadb.mmontes.io/v1alpha1 +kind: Grant +metadata: + name: keystone-grant + namespace: openstack +spec: + mariaDbRef: + name: mariadb # name of the MariaDB kind + waitForIt: true + privileges: + - "ALL" + database: "keystone" + table: "*" + username: keystone + grantOption: true + host: "%" + retryInterval: 5s diff --git a/components/10-keystone/keystone-rabbitmq-queue.yaml b/components/10-keystone/keystone-rabbitmq-queue.yaml new file mode 100644 index 000000000..da301b8c7 --- /dev/null +++ b/components/10-keystone/keystone-rabbitmq-queue.yaml @@ -0,0 +1,59 @@ +--- +apiVersion: rabbitmq.com/v1beta1 +kind: User +metadata: + name: keystone + namespace: openstack +spec: + tags: + - management # available tags are 'management', 'policymaker', 'monitoring' and 'administrator' + - policymaker + rabbitmqClusterReference: + name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource + namespace: openstack + importCredentialsSecret: + name: keystone-rabbitmq-password +--- +apiVersion: rabbitmq.com/v1beta1 +kind: Vhost +metadata: + name: keystone-vhost + namespace: openstack +spec: + name: "keystone" # vhost name; required and cannot be updated + defaultQueueType: quorum # default queue type for this vhost; require RabbitMQ version 3.11.12 or above + rabbitmqClusterReference: + name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource + namespace: openstack +--- +apiVersion: rabbitmq.com/v1beta1 +kind: Queue +metadata: + name: keystone-queue + namespace: openstack +spec: + name: keystone-qq # name of the queue + vhost: "keystone" # default to '/' if not provided + type: quorum # without providing a queue type, rabbitmq creates a classic queue + autoDelete: false + durable: true # seting 'durable' to false means this queue won't survive a server restart + rabbitmqClusterReference: + name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource + namespace: openstack +--- +apiVersion: rabbitmq.com/v1beta1 +kind: Permission +metadata: + name: keystone-permission + namespace: openstack +spec: + vhost: "keystone" # name of a vhost + userReference: + name: "keystone" # name of a user.rabbitmq.com in the same namespace; must specify either spec.userReference or spec.user + permissions: + write: ".*" + configure: ".*" + read: ".*" + rabbitmqClusterReference: + name: rabbitmq # rabbitmqCluster must exist in the same namespace as this resource + namespace: openstack diff --git a/components/10-keystone/kustomization.yaml b/components/10-keystone/kustomization.yaml new file mode 100644 index 000000000..d66eedff3 --- /dev/null +++ b/components/10-keystone/kustomization.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - keystone-mariadb-db.yaml + - keystone-rabbitmq-queue.yaml