resource "kubectl_manifest" "cm_env_back" { yaml_body = <<-EOF apiVersion: v1 kind: ConfigMap metadata: name: "${var.instance}-${var.component}-back" labels: ${jsonencode(local.common_labels)} namespace: ${var.namespace} data: POSTGRES_DB: ${var.component} POSTGRES_USER: ${var.component} POSTGRES_HOST: ${var.instance}-${var.component}-pg-rw.${var.namespace}.svc TAIGA_URL: https://${local.dns_name} TAIGA_SITES_DOMAIN: ${local.dns_name} TAIGA_SITES_SCHEME: https TAIGA_ASYNC_RABBITMQ_HOST: ${kubectl_manifest.rabbit.name} TAIGA_EVENTS_RABBITMQ_HOST: ${kubectl_manifest.rabbit.name} ENABLE_TELEMETRY: "False" PUBLIC_REGISTER_ENABLED: "False" ENABLE_OPENID_AUTH: "True" OPENID_SCOPE: "openid email profile" OPENID_TOKEN_URL: "${module.oauth2.sso_token_url}" OPENID_USER_URL: "${module.oauth2.sso_userinfo_url}" DEBUG: "True" EOF } resource "kubectl_manifest" "cm_env_front" { yaml_body = <<-EOF apiVersion: v1 kind: ConfigMap metadata: name: "${var.instance}-${var.component}-front" labels: ${jsonencode(local.common_labels)} namespace: ${var.namespace} data: TAIGA_URL: https://${local.dns_name} TAIGA_SITES_DOMAIN: ${local.dns_name} TAIGA_SITES_SCHEME: https SESSION_COOKIE_SECURE: "false" CSRF_COOKIE_SECURE: "false" ENABLE_TELEMETRY: "false" PUBLIC_REGISTER_ENABLED: "true" ENABLE_GITHUB_AUTH: "false" ENABLE_GITLAB_AUTH: "false" ENABLE_SLACK: "false" ENABLE_GITHUB_IMPORTER: "false" ENABLE_JIRA_IMPORTER: "false" ENABLE_TRELLO_IMPORTER: "false" ENABLE_OIDC_AUTH: "false" ENABLE_OPENID_AUTH: "true" OPENID_URL: "${module.oauth2.sso_authorize_url}" OPENID_SCOPE: "openid email profile" OPENID_NAME: "${var.domain}" EOF } # awk '/taiga-events-rabbitmq/||/taiga-async-rabbitmq/' < /taiga-back/settings/config.py # EVENTS_PUSH_BACKEND_URL = f"amqp://{ os.getenv('RABBITMQ_USER') }:{ os.getenv('RABBITMQ_PASS') }@taiga-events-rabbitmq:5672/taiga" # CELERY_BROKER_URL = f"amqp://{ os.getenv('RABBITMQ_USER') }:{ os.getenv('RABBITMQ_PASS') }@taiga-async-rabbitmq:5672/taiga" resource "kubectl_manifest" "cm_scripts" { yaml_body = <<-EOF apiVersion: v1 kind: ConfigMap metadata: name: "${var.instance}-${var.component}-scripts" labels: ${jsonencode(local.postcfg_all_labels)} namespace: ${var.namespace} data: config.py: |- # -*- coding: utf-8 -*- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # Copyright (c) 2021-present Kaleidos INC from .common import * from ldap3 import Tls import os, sys, ssl ######################################### ## GENERIC ######################################### DEBUG = os.getenv('DEBUG', 'False') == 'True' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.getenv('POSTGRES_DB'), 'USER': os.getenv('POSTGRES_USER'), 'PASSWORD': os.getenv('POSTGRES_PASSWORD'), 'HOST': os.getenv('POSTGRES_HOST'), 'PORT': os.getenv('POSTGRES_PORT','5432'), 'OPTIONS': {'sslmode': os.getenv('POSTGRES_SSLMODE','disable')}, 'DISABLE_SERVER_SIDE_CURSORS': os.getenv('POSTGRES_DISABLE_SERVER_SIDE_CURSORS', 'False') == 'True', } } SECRET_KEY = os.getenv('TAIGA_SECRET_KEY') TAIGA_SITES_SCHEME = os.getenv('TAIGA_SITES_SCHEME', "http") TAIGA_SITES_DOMAIN = os.getenv('TAIGA_SITES_DOMAIN', "localhost") FORCE_SCRIPT_NAME = os.getenv('TAIGA_SUBPATH', '') TAIGA_URL = f"{ TAIGA_SITES_SCHEME }://{ TAIGA_SITES_DOMAIN }{ FORCE_SCRIPT_NAME }" SITES = { "api": { "name": "api", "scheme": TAIGA_SITES_SCHEME, "domain": TAIGA_SITES_DOMAIN }, "front": { "name": "front", "scheme": TAIGA_SITES_SCHEME, "domain": f"{ TAIGA_SITES_DOMAIN }{ FORCE_SCRIPT_NAME }" } } LANGUAGE_CODE = os.getenv("LANGUAGE_CODE", "en-us") INSTANCE_TYPE = "D" WEBHOOKS_ENABLED = os.getenv('WEBHOOKS_ENABLED', 'True') == 'True' WEBHOOKS_ALLOW_PRIVATE_ADDRESS = os.getenv('WEBHOOKS_ALLOW_PRIVATE_ADDRESS', 'False') == 'True' WEBHOOKS_ALLOW_REDIRECTS = os.getenv('WEBHOOKS_ALLOW_REDIRECTS', 'False') == 'True' # Setting DEFAULT_PROJECT_SLUG_PREFIX to false # removes the username from project slug DEFAULT_PROJECT_SLUG_PREFIX = os.getenv('DEFAULT_PROJECT_SLUG_PREFIX', 'False') == 'True' ######################################### ## MEDIA ######################################### MEDIA_URL = f"{ TAIGA_URL }/media/" DEFAULT_FILE_STORAGE = "taiga_contrib_protected.storage.ProtectedFileSystemStorage" THUMBNAIL_DEFAULT_STORAGE = DEFAULT_FILE_STORAGE STATIC_URL = f"{ TAIGA_URL }/static/" ######################################### ## EMAIL ######################################### # https://docs.djangoproject.com/en/3.1/topics/email/ EMAIL_BACKEND = os.getenv('EMAIL_BACKEND', 'django.core.mail.backends.console.EmailBackend') CHANGE_NOTIFICATIONS_MIN_INTERVAL = 120 # seconds DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', 'system@taiga.io') EMAIL_USE_TLS = os.getenv('EMAIL_USE_TLS', 'False') == 'True' EMAIL_USE_SSL = os.getenv('EMAIL_USE_SSL', 'False') == 'True' EMAIL_HOST = os.getenv('EMAIL_HOST', 'localhost') EMAIL_PORT = os.getenv('EMAIL_PORT', 587) EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER', 'user') EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD', 'password') ######################################### ## SESSION ######################################### SESSION_COOKIE_SECURE = os.getenv('SESSION_COOKIE_SECURE', 'True') == 'True' CSRF_COOKIE_SECURE = os.getenv('CSRF_COOKIE_SECURE', 'True') == 'True' ######################################### ## EVENTS ######################################### EVENTS_PUSH_BACKEND = "taiga.events.backends.rabbitmq.EventsPushBackend" EVENTS_PUSH_BACKEND_URL = os.getenv('EVENTS_PUSH_BACKEND_URL') if not EVENTS_PUSH_BACKEND_URL: EVENTS_PUSH_BACKEND_URL = f"amqp://{ os.getenv('RABBITMQ_USER') }:{ os.getenv('RABBITMQ_PASS') }@{ os.getenv('TAIGA_EVENTS_RABBITMQ_HOST', 'taiga-events-rabbitmq') }:5672/taiga" EVENTS_PUSH_BACKEND_OPTIONS = { "url": EVENTS_PUSH_BACKEND_URL } ######################################### ## TAIGA ASYNC ######################################### CELERY_ENABLED = os.getenv('CELERY_ENABLED', 'True') == 'True' from kombu import Queue # noqa CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL') if not CELERY_BROKER_URL: CELERY_BROKER_URL = f"amqp://{ os.getenv('RABBITMQ_USER') }:{ os.getenv('RABBITMQ_PASS') }@{ os.getenv('TAIGA_ASYNC_RABBITMQ_HOST', 'taiga-async-rabbitmq') }:5672/taiga" CELERY_RESULT_BACKEND = None # for a general installation, we don't need to store the results CELERY_ACCEPT_CONTENT = ['pickle', ] # Values are 'pickle', 'json', 'msgpack' and 'yaml' CELERY_TASK_SERIALIZER = "pickle" CELERY_RESULT_SERIALIZER = "pickle" CELERY_TIMEZONE = os.getenv('CELERY_TIMEZONE', 'Europe/Madrid') CELERY_TASK_DEFAULT_QUEUE = 'tasks' CELERY_QUEUES = ( Queue('tasks', routing_key='task.#'), Queue('transient', routing_key='transient.#', delivery_mode=1) ) CELERY_TASK_DEFAULT_EXCHANGE = 'tasks' CELERY_TASK_DEFAULT_EXCHANGE_TYPE = 'topic' CELERY_TASK_DEFAULT_ROUTING_KEY = 'task.default' ######################################### ## REGISTRATION ######################################### PUBLIC_REGISTER_ENABLED = os.getenv('PUBLIC_REGISTER_ENABLED', 'False') == 'True' ######################################### ## CONTRIBS ######################################### # SLACK ENABLE_SLACK = os.getenv('ENABLE_SLACK', 'False') == 'True' if ENABLE_SLACK: INSTALLED_APPS += [ "taiga_contrib_slack" ] # GITHUB AUTH # WARNING: If PUBLIC_REGISTER_ENABLED == False, currently Taiga by default prevents the OAuth # buttons to appear for both login and register ENABLE_GITHUB_AUTH = os.getenv('ENABLE_GITHUB_AUTH', 'False') == 'True' if PUBLIC_REGISTER_ENABLED and ENABLE_GITHUB_AUTH: INSTALLED_APPS += [ "taiga_contrib_github_auth" ] GITHUB_API_CLIENT_ID = os.getenv('GITHUB_API_CLIENT_ID') GITHUB_API_CLIENT_SECRET = os.getenv('GITHUB_API_CLIENT_SECRET') # GITLAB AUTH # WARNING: If PUBLIC_REGISTER_ENABLED == False, currently Taiga by default prevents the OAuth # buttons to appear for both login and register ENABLE_GITLAB_AUTH = os.getenv('ENABLE_GITLAB_AUTH', 'False') == 'True' if PUBLIC_REGISTER_ENABLED and ENABLE_GITLAB_AUTH: INSTALLED_APPS += [ "taiga_contrib_gitlab_auth" ] GITLAB_API_CLIENT_ID = os.getenv('GITLAB_API_CLIENT_ID') GITLAB_API_CLIENT_SECRET = os.getenv('GITLAB_API_CLIENT_SECRET') GITLAB_URL = os.getenv('GITLAB_URL') # OIDC AUTH ENABLE_OIDC_AUTH = os.getenv('ENABLE_OIDC_AUTH', 'False') == 'True' if ENABLE_OIDC_AUTH: INSTALLED_APPS += [ "mozilla_django_oidc", "taiga_contrib_oidc_auth", ] AUTHENTICATION_BACKENDS = list(AUTHENTICATION_BACKENDS) + [ "taiga_contrib_oidc_auth.oidc.TaigaOIDCAuthenticationBackend", ] ROOT_URLCONF = "settings.urls" OIDC_CALLBACK_CLASS = "taiga_contrib_oidc_auth.views.TaigaOIDCAuthenticationCallbackView" OIDC_BASE_URL = os.getenv("OIDC_BASE_URL", "https://id.fedoraproject.org/openidc") OIDC_RP_SCOPES = os.getenv("OIDC_RP_SCOPES", "openid profile email") OIDC_RP_SIGN_ALGO = os.getenv("OIDC_RP_SIGN_ALGO", "RS256") OIDC_OP_JWKS_ENDPOINT = os.getenv("OIDC_OP_JWKS_ENDPOINT", OIDC_BASE_URL + "/Jwks") OIDC_OP_AUTHORIZATION_ENDPOINT = os.getenv("OIDC_OP_AUTHORIZATION_ENDPOINT", OIDC_BASE_URL + "/Authorization") OIDC_OP_TOKEN_ENDPOINT = os.getenv("OIDC_OP_TOKEN_ENDPOINT", OIDC_BASE_URL + "/Token") OIDC_OP_USER_ENDPOINT = os.getenv("OIDC_OP_USER_ENDPOINT", OIDC_BASE_URL + "/UserInfo") OIDC_RP_CLIENT_ID = os.getenv("OIDC_RP_CLIENT_ID") OIDC_RP_CLIENT_SECRET = os.getenv("OIDC_RP_CLIENT_SECRET") if os.getenv('TAIGA_ENABLE_OPENID_AUTH', os.getenv('ENABLE_OPENID', 'False')).lower() == 'true': print("ENABLE_OPENID") INSTALLED_APPS += ["taiga_contrib_openid_auth"] OPENID_USER_URL = os.getenv('TAIGA_OPENID_AUTH_USER_URL', os.getenv('OPENID_USER_URL')) OPENID_TOKEN_URL = os.getenv('TAIGA_OPENID_AUTH_TOKEN_URL', os.getenv('OPENID_TOKEN_URL')) OPENID_CLIENT_ID = os.getenv('TAIGA_OPENID_AUTH_CLIENT_ID', os.getenv('OPENID_CLIENT_ID')) OPENID_CLIENT_SECRET = os.getenv('TAIGA_OPENID_AUTH_CLIENT_SECRET', os.getenv('OPENID_CLIENT_SECRET')) OPENID_SCOPE = os.getenv('TAIGA_OPENID_SCOPE', os.getenv('OPENID_SCOPE')) if os.getenv('TAIGA_ENABLE_LDAP', os.getenv('ENABLE_LDAP', 'False')).lower() == 'true': INSTALLED_APPS += ["taiga_contrib_ldap_auth_ext"] if os.getenv('TAIGA_LDAP_USE_TLS', os.getenv('LDAP_START_TLS', 'False')).lower() == 'true': # Flag to enable LDAP with STARTTLS before bind LDAP_START_TLS = True LDAP_TLS_CERTS = Tls(validate=ssl.CERT_NONE, version=ssl.PROTOCOL_TLSv1, ciphers='RSA+3DES') else: LDAP_START_TLS = False LDAP_SERVER = os.getenv('TAIGA_LDAP_SERVER', os.getenv('LDAP_SERVER')) LDAP_PORT = int(os.getenv('TAIGA_LDAP_PORT', os.getenv('LDAP_PORT', '389'))) # Full DN of the service account use to connect to LDAP server and search for login user's account entry # If LDAP_BIND_DN is not specified, or is blank, then an anonymous bind is attempated LDAP_BIND_DN = os.getenv('TAIGA_LDAP_BIND_DN', os.getenv('LDAP_BIND_DN')) LDAP_BIND_PASSWORD = os.getenv('TAIGA_LDAP_BIND_PASSWORD', os.getenv('LDAP_BIND_PASSWORD')) # Starting point within LDAP structure to search for login user # Something like 'ou=People,dc=company,dc=com' LDAP_SEARCH_BASE = os.getenv('TAIGA_LDAP_BASE_DN', os.getenv('LDAP_SEARCH_BASE')) # Additional search criteria to the filter (will be ANDed) #LDAP_SEARCH_FILTER_ADDITIONAL = '(mail=*)' # Names of attributes to get username, e-mail and full name values from # These fields need to have a value in LDAP LDAP_USERNAME_ATTRIBUTE = os.getenv('TAIGA_LDAP_USERNAME_ATTRIBUTE', os.getenv('LDAP_USERNAME_ATTRIBUTE')) LDAP_EMAIL_ATTRIBUTE = os.getenv('TAIGA_LDAP_EMAIL_ATTRIBUTE', os.getenv('LDAP_EMAIL_ATTRIBUTE')) LDAP_FULL_NAME_ATTRIBUTE = os.getenv('TAIGA_LDAP_FULL_NAME_ATTRIBUTE', os.getenv('LDAP_FULL_NAME_ATTRIBUTE')) # Option to not store the passwords in the local db if os.getenv('TAIGA_LDAP_SAVE_LOGIN_PASSWORD', os.getenv('LDAP_SAVE_LOGIN_PASSWORD', 'False')).lower() == 'false': LDAP_SAVE_LOGIN_PASSWORD = False # Fallback on normal authentication method if this LDAP auth fails. Uncomment to enable. LDAP_FALLBACK = os.getenv('TAIGA_LDAP_FALLBACK', os.getenv('LDAP_FALLBACK', 'normal')) # Function to map LDAP username to local DB user unique identifier. # Upon successful LDAP bind, will override returned username attribute # value. May result in unexpected failures if changed after the database # has been populated. def _ldap_slugify(uid: str) -> str: # example: force lower-case uid = uid.lower() return uid LDAP_MAP_USERNAME_TO_UID = _ldap_slugify ######################################### ## TELEMETRY ######################################### ENABLE_TELEMETRY = os.getenv('ENABLE_TELEMETRY', 'True') == 'True' ######################################### ## IMPORTERS ######################################### ENABLE_GITHUB_IMPORTER = os.getenv('ENABLE_GITHUB_IMPORTER', 'False') == 'True' if ENABLE_GITHUB_IMPORTER: IMPORTERS["github"] = { "active": True, "client_id": os.getenv('GITHUB_IMPORTER_CLIENT_ID'), "client_secret": os.getenv('GITHUB_IMPORTER_CLIENT_SECRET') } ENABLE_JIRA_IMPORTER = os.getenv('ENABLE_JIRA_IMPORTER', 'False') == 'True' if ENABLE_JIRA_IMPORTER: IMPORTERS["jira"] = { "active": True, "consumer_key": os.getenv('JIRA_IMPORTER_CONSUMER_KEY'), "cert": os.getenv('JIRA_IMPORTER_CERT'), "pub_cert": os.getenv('JIRA_IMPORTER_PUB_CERT') } ENABLE_TRELLO_IMPORTER = os.getenv('ENABLE_TRELLO_IMPORTER', 'False') == 'True' if ENABLE_TRELLO_IMPORTER: IMPORTERS["trello"] = { "active": True, "api_key": os.getenv('TRELLO_IMPORTER_API_KEY'), "secret_key": os.getenv('TRELLO_IMPORTER_SECRET_KEY') } certs.sh: |- #!/usr/bin/env bash if [ -f /etc/local-ca/ca.crt ];then export REQUESTS_CA_BUNDLE=/etc/local-ca/ca.crt else export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt fi postconfig.py: |- #!/usr/bin/env python import time import requests import subprocess print('Waiting for backend ...') while requests.get('http://${kubectl_manifest.svc_back.name}/api/v1/').status_code != 200: print('...') time.sleep(2) if len(str(subprocess.check_output(['python', 'manage.py', 'dumpdata', 'projects.projecttemplate']))) < 5: print(subprocess.check_output(['python', 'manage.py', 'loaddata', 'initial_project_templates'])) if str(subprocess.check_output(['python', 'manage.py', 'dumpdata', 'users.user'], cwd='/taiga-back')).find('\"is_superuser\": true') == -1: print(subprocess.check_output(['python', 'manage.py', 'loaddata', 'initial_user'], cwd='/taiga-back')) EOF } resource "kubectl_manifest" "cm_nginx" { yaml_body = <<-EOF apiVersion: v1 kind: ConfigMap metadata: name: "${var.instance}-${var.component}-nginx" namespace: ${var.namespace} labels: ${jsonencode(local.common_labels)} data: default.conf: |- server { listen 8080 default_server; client_max_body_size 100M; charset utf-8; # Frontend location / { proxy_pass http://${kubectl_manifest.svc_front.name}/; proxy_pass_header Server; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; } # Api location /api { proxy_pass http://${kubectl_manifest.svc_back.name}:8000/api; proxy_pass_header Server; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; } # Admin location /admin { proxy_pass http://${kubectl_manifest.svc_back.name}:8000/admin; proxy_pass_header Server; proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; } # Static location /static { root /taiga; } # Media location /_protected { internal; alias /taiga/media/; add_header Content-disposition "attachment"; } # Unprotected section location /media/exports { alias /taiga/media/exports/; add_header Content-disposition "attachment"; } location /media { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://${kubectl_manifest.svc_protected.name}:8003/; proxy_redirect off; } # Events location /events { proxy_pass http://${kubectl_manifest.svc_events.name}:8888/events; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; } } EOF }