diff --git a/kubernetes/argocd/applications/netbox.yaml b/kubernetes/argocd/applications/netbox.yaml index c6fa21f1..229c4b29 100644 --- a/kubernetes/argocd/applications/netbox.yaml +++ b/kubernetes/argocd/applications/netbox.yaml @@ -20,6 +20,8 @@ spec: path: kubernetes/netbox/overlays/okd repoURL: https://git.arthurvardevanyan.com/ArthurVardevanyan/HomeLab targetRevision: HEAD + plugin: + name: argocd-vault-plugin-kustomize syncPolicy: syncOptions: - CreateNamespace=true diff --git a/kubernetes/netbox/base/configmap.yaml b/kubernetes/netbox/base/configmap.yaml deleted file mode 100644 index aa4a4b9a..00000000 --- a/kubernetes/netbox/base/configmap.yaml +++ /dev/null @@ -1,189 +0,0 @@ -# Source: netbox/templates/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: netbox-config - namespace: "netbox" - labels: - app.kubernetes.io/instance: netbox - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: netbox - app.kubernetes.io/version: v4.0.0 - helm.sh/chart: netbox-5.0.0-beta9 -data: - configuration.py: |- - import re - from pathlib import Path - - import yaml - - - def _deep_merge(source, destination): - """Inspired by https://stackoverflow.com/a/20666342""" - for key, value in source.items(): - dst_value = destination.get(key) - - if isinstance(value, dict) and isinstance(dst_value, dict): - _deep_merge(value, dst_value) - else: - destination[key] = value - - return destination - - - def _load_yaml(): - extraConfigBase = Path("/run/config/extra") - configFiles = [Path("/run/config/netbox/netbox.yaml")] - - configFiles.extend(sorted(extraConfigBase.glob("*/*.yaml"))) - - for configFile in configFiles: - with open(configFile, "r") as f: - config = yaml.safe_load(f) - - _deep_merge(config, globals()) - - - def _load_secret(name, key): - path = "/run/secrets/{name}/{key}".format(name=name, key=key) - with open(path, "r") as f: - return f.read() - - - CORS_ORIGIN_REGEX_WHITELIST = list() - DATABASE = dict() - EMAIL = dict() - REDIS = dict() - - _load_yaml() - - DATABASE["PASSWORD"] = _load_secret("netbox", "db_password") - EMAIL["PASSWORD"] = _load_secret("netbox", "email_password") - REDIS["tasks"]["PASSWORD"] = _load_secret("netbox", "redis_tasks_password") - REDIS["caching"]["PASSWORD"] = _load_secret("netbox", "redis_cache_password") - SECRET_KEY = _load_secret("netbox", "secret_key") - - # Post-process certain values - CORS_ORIGIN_REGEX_WHITELIST = [re.compile(r) for r in CORS_ORIGIN_REGEX_WHITELIST] - - netbox.yaml: |- - ALLOWED_HOSTS: ["*"] - - DATABASE: - HOST: "netbox-primary.netbox.svc" - USER: "netbox" - NAME: "netbox" - PORT: 5432 - OPTIONS: - sslmode: "prefer" - target_session_attrs: "read-write" - CONN_MAX_AGE: 300 - DISABLE_SERVER_SIDE_CURSORS: false - - ADMINS: [] - ALLOW_TOKEN_RETRIEVAL: false - AUTH_PASSWORD_VALIDATORS: [] - ALLOWED_URL_SCHEMES: ["file","ftp","ftps","http","https","irc","mailto","sftp","ssh","tel","telnet","tftp","vnc","xmpp"] - BANNER_TOP: "" - BANNER_BOTTOM: "" - BANNER_LOGIN: "" - BASE_PATH: "" - CHANGELOG_RETENTION: 90 - CUSTOM_VALIDATORS: {} - DEFAULT_USER_PREFERENCES: {} - CORS_ORIGIN_ALLOW_ALL: false - CORS_ORIGIN_WHITELIST: [] - CORS_ORIGIN_REGEX_WHITELIST: [] - CSRF_TRUSTED_ORIGINS: [] - DATA_UPLOAD_MAX_MEMORY_SIZE: 2621440 - DEBUG: false - DEFAULT_LANGUAGE: "en-us" - - EMAIL: - SERVER: "localhost" - PORT: 25 - USERNAME: "" - USE_SSL: false - USE_TLS: false - SSL_CERTFILE: "" - SSL_KEYFILE: "" - TIMEOUT: 10 - FROM_EMAIL: "" - - ENFORCE_GLOBAL_UNIQUE: false - EXEMPT_VIEW_PERMISSIONS: [] - FIELD_CHOICES: {} - FILE_UPLOAD_MAX_MEMORY_SIZE: 2621440 - GRAPHQL_ENABLED: true - HTTP_PROXIES: {} - INTERNAL_IPS: ["127.0.0.1","::1"] - JOB_RETENTION: 90 - LOGGING: {} - LOGIN_PERSISTENCE: false - LOGIN_REQUIRED: false - LOGIN_TIMEOUT: 1209600 - LOGOUT_REDIRECT_URL: "home" - MAINTENANCE_MODE: false - MAPS_URL: "https://maps.google.com/?q=" - MAX_PAGE_SIZE: 1000 - MEDIA_ROOT: /opt/netbox/netbox/media - METRICS_ENABLED: false - PAGINATE_COUNT: 50 - PLUGINS: [] - PLUGINS_CONFIG: {} - POWERFEED_DEFAULT_AMPERAGE: 15 - POWERFEED_DEFAULT_MAX_UTILIZATION: 80 - POWERFEED_DEFAULT_VOLTAGE: 120 - PREFER_IPV4: false - RACK_ELEVATION_DEFAULT_UNIT_HEIGHT: 22 - RACK_ELEVATION_DEFAULT_UNIT_WIDTH: 220 - REMOTE_AUTH_ENABLED: false - REMOTE_AUTH_BACKEND: ["netbox.authentication.RemoteUserBackend"] - REMOTE_AUTH_HEADER: "HTTP_REMOTE_USER" - REMOTE_AUTH_USER_FIRST_NAME: "HTTP_REMOTE_USER_FIRST_NAME" - REMOTE_AUTH_USER_LAST_NAME: "HTTP_REMOTE_USER_LAST_NAME" - REMOTE_AUTH_USER_EMAIL: "HTTP_REMOTE_USER_EMAIL" - REMOTE_AUTH_AUTO_CREATE_USER: false - REMOTE_AUTH_AUTO_CREATE_GROUPS: false - REMOTE_AUTH_DEFAULT_GROUPS: [] - REMOTE_AUTH_DEFAULT_PERMISSIONS: {} - REMOTE_AUTH_GROUP_SYNC_ENABLED: false - REMOTE_AUTH_GROUP_HEADER: "HTTP_REMOTE_USER_GROUP" - REMOTE_AUTH_SUPERUSER_GROUPS: [] - REMOTE_AUTH_SUPERUSERS: [] - REMOTE_AUTH_STAFF_GROUPS: [] - REMOTE_AUTH_STAFF_USERS: [] - REMOTE_AUTH_GROUP_SEPARATOR: "|" - RELEASE_CHECK_URL: "" - - REDIS: - tasks: - HOST: "netbox-dragonfly.netbox.svc.cluster.local" - PORT: 6379 - USERNAME: "" - DATABASE: 0 - SSL: false - INSECURE_SKIP_TLS_VERIFY: false - CA_CERT_PATH: "" - caching: - HOST: "netbox-dragonfly.netbox.svc.cluster.local" - PORT: 6379 - USERNAME: "" - DATABASE: 1 - SSL: false - INSECURE_SKIP_TLS_VERIFY: false - CA_CERT_PATH: "" - - REPORTS_ROOT: /opt/netbox/netbox/reports - RQ_DEFAULT_TIMEOUT: 300 - SCRIPTS_ROOT: /opt/netbox/netbox/scripts - CSRF_COOKIE_NAME: "csrftoken" - SESSION_COOKIE_NAME: sessionid - ENABLE_LOCALIZATION: false - TIME_ZONE: "UTC" - DATE_FORMAT: "N j, Y" - SHORT_DATE_FORMAT: "Y-m-d" - TIME_FORMAT: "g:i a" - SHORT_TIME_FORMAT: "H:i:s" - DATETIME_FORMAT: "N j, Y g:i a" - SHORT_DATETIME_FORMAT: "Y-m-d H:i" diff --git a/kubernetes/netbox/base/configs/configuration.py b/kubernetes/netbox/base/configs/configuration.py new file mode 100644 index 00000000..d1f60457 --- /dev/null +++ b/kubernetes/netbox/base/configs/configuration.py @@ -0,0 +1,53 @@ +import re +from pathlib import Path + +import yaml + + +def _deep_merge(source, destination): + """Inspired by https://stackoverflow.com/a/20666342""" + for key, value in source.items(): + dst_value = destination.get(key) + + if isinstance(value, dict) and isinstance(dst_value, dict): + _deep_merge(value, dst_value) + else: + destination[key] = value + + return destination + + +def _load_yaml(): + extraConfigBase = Path("/run/config/extra") + configFiles = [Path("/run/config/netbox/netbox.yaml")] + + configFiles.extend(sorted(extraConfigBase.glob("*/*.yaml"))) + + for configFile in configFiles: + with open(configFile, "r") as f: + config = yaml.safe_load(f) + + _deep_merge(config, globals()) + + +def _load_secret(name, key): + path = "/run/secrets/{name}/{key}".format(name=name, key=key) + with open(path, "r") as f: + return f.read() + + +CORS_ORIGIN_REGEX_WHITELIST = list() +DATABASE = dict() +EMAIL = dict() +REDIS = dict() + +_load_yaml() + +DATABASE["PASSWORD"] = _load_secret("netbox", "db_password") +EMAIL["PASSWORD"] = _load_secret("netbox", "email_password") +REDIS["tasks"]["PASSWORD"] = _load_secret("netbox", "redis_tasks_password") +REDIS["caching"]["PASSWORD"] = _load_secret("netbox", "redis_cache_password") +SECRET_KEY = _load_secret("netbox", "secret_key") + +# Post-process certain values +CORS_ORIGIN_REGEX_WHITELIST = [re.compile(r) for r in CORS_ORIGIN_REGEX_WHITELIST] diff --git a/kubernetes/netbox/base/configs/netbox.yaml b/kubernetes/netbox/base/configs/netbox.yaml new file mode 100644 index 00000000..3529322a --- /dev/null +++ b/kubernetes/netbox/base/configs/netbox.yaml @@ -0,0 +1,150 @@ +ALLOWED_HOSTS: ["*"] + +DATABASE: + HOST: "netbox-primary.netbox.svc" + USER: "netbox" + NAME: "netbox" + PORT: 5432 + OPTIONS: + sslmode: "prefer" + target_session_attrs: "read-write" + CONN_MAX_AGE: 300 + DISABLE_SERVER_SIDE_CURSORS: false + +ADMINS: [] +ALLOW_TOKEN_RETRIEVAL: false +AUTH_PASSWORD_VALIDATORS: [] +ALLOWED_URL_SCHEMES: + [ + "file", + "ftp", + "ftps", + "http", + "https", + "irc", + "mailto", + "sftp", + "ssh", + "tel", + "telnet", + "tftp", + "vnc", + "xmpp", + ] +BANNER_TOP: "" +BANNER_BOTTOM: "" +BANNER_LOGIN: "" +BASE_PATH: "" +CHANGELOG_RETENTION: 90 +CUSTOM_VALIDATORS: {} +DEFAULT_USER_PREFERENCES: {} +CORS_ORIGIN_ALLOW_ALL: false +CORS_ORIGIN_WHITELIST: [] +CORS_ORIGIN_REGEX_WHITELIST: [] +CSRF_TRUSTED_ORIGINS: [] +DATA_UPLOAD_MAX_MEMORY_SIZE: 2621440 +DEBUG: false +DEFAULT_LANGUAGE: "en-us" + +EMAIL: + SERVER: "localhost" + PORT: 25 + USERNAME: "" + USE_SSL: false + USE_TLS: false + SSL_CERTFILE: "" + SSL_KEYFILE: "" + TIMEOUT: 10 + FROM_EMAIL: "" + +ENFORCE_GLOBAL_UNIQUE: false +EXEMPT_VIEW_PERMISSIONS: [] +FIELD_CHOICES: {} +FILE_UPLOAD_MAX_MEMORY_SIZE: 2621440 +GRAPHQL_ENABLED: true +HTTP_PROXIES: {} +INTERNAL_IPS: ["127.0.0.1", "::1"] +JOB_RETENTION: 90 +LOGGING: {} +LOGIN_PERSISTENCE: false +LOGIN_REQUIRED: false +LOGIN_TIMEOUT: 1209600 +LOGOUT_REDIRECT_URL: "home" +MAINTENANCE_MODE: false +MAPS_URL: "https://maps.google.com/?q=" +MAX_PAGE_SIZE: 1000 +MEDIA_ROOT: /opt/netbox/netbox/media +METRICS_ENABLED: false +PAGINATE_COUNT: 50 +PLUGINS: [] +PLUGINS_CONFIG: {} +POWERFEED_DEFAULT_AMPERAGE: 15 +POWERFEED_DEFAULT_MAX_UTILIZATION: 80 +POWERFEED_DEFAULT_VOLTAGE: 120 +PREFER_IPV4: false +RACK_ELEVATION_DEFAULT_UNIT_HEIGHT: 22 +RACK_ELEVATION_DEFAULT_UNIT_WIDTH: 220 + +REMOTE_AUTH_ENABLED: True +SOCIAL_AUTH_REDIRECT_IS_HTTPS: True +REMOTE_AUTH_BACKEND: ["social_core.backends.open_id_connect.OpenIdConnectAuth"] +SOCIAL_AUTH_OIDC_OIDC_ENDPOINT: "https://zitadel.apps.okd.arthurvardevanyan.com" +SOCIAL_AUTH_OIDC_KEY: "" +SOCIAL_AUTH_OIDC_SECRET: "" +REMOTE_AUTH_AUTO_CREATE_USER: True +REMOTE_AUTH_AUTO_CREATE_GROUPS: True +REMOTE_AUTH_GROUP_SYNC_ENABLED: True + +# Manual Config Required, Not Sticking +# Auto Revoke is not applying either: +# https://netbox.uemasul.edu.br/static/docs/configuration/remote-authentication/#remote_auth_staff_users +REMOTE_AUTH_STAFF_USERS: ["ArthurVardevanyan"] +REMOTE_AUTH_SUPERUSERS: ["ArthurVardevanyan"] + +# REMOTE_AUTH_BACKEND: ["social_core.backends.openshift.OpenshiftOAuth2"] +# SOCIAL_AUTH_OPENSHIFT_KEY: "netbox" +# # SOCIAL_AUTH_OPENSHIFT_SECRET": "test" +# SOCIAL_AUTH_OPENSHIFT_URL: "https://oauth-openshift.apps.okd.arthurvardevanyan.com" + +REMOTE_AUTH_DEFAULT_PERMISSIONS: {} +REMOTE_AUTH_DEFAULT_GROUPS: [] +REMOTE_AUTH_STAFF_GROUPS: [] +REMOTE_AUTH_SUPERUSER_GROUPS: [] +REMOTE_AUTH_USER_FIRST_NAME: "HTTP_REMOTE_USER_FIRST_NAME" +REMOTE_AUTH_USER_LAST_NAME: "HTTP_REMOTE_USER_LAST_NAME" +REMOTE_AUTH_USER_EMAIL: "HTTP_REMOTE_USER_EMAIL" +REMOTE_AUTH_GROUP_HEADER: "HTTP_REMOTE_USER_GROUP" +REMOTE_AUTH_GROUP_SEPARATOR: "|" +RELEASE_CHECK_URL: "" + +REDIS: + tasks: + HOST: "netbox-dragonfly.netbox.svc.cluster.local" + PORT: 6379 + USERNAME: "" + DATABASE: 0 + SSL: false + INSECURE_SKIP_TLS_VERIFY: false + CA_CERT_PATH: "" + caching: + HOST: "netbox-dragonfly.netbox.svc.cluster.local" + PORT: 6379 + USERNAME: "" + DATABASE: 1 + SSL: false + INSECURE_SKIP_TLS_VERIFY: false + CA_CERT_PATH: "" + +REPORTS_ROOT: /opt/netbox/netbox/reports +RQ_DEFAULT_TIMEOUT: 300 +SCRIPTS_ROOT: /opt/netbox/netbox/scripts +CSRF_COOKIE_NAME: "csrftoken" +SESSION_COOKIE_NAME: sessionid +ENABLE_LOCALIZATION: false +TIME_ZONE: "UTC" +DATE_FORMAT: "N j, Y" +SHORT_DATE_FORMAT: "Y-m-d" +TIME_FORMAT: "g:i a" +SHORT_TIME_FORMAT: "H:i:s" +DATETIME_FORMAT: "N j, Y g:i a" +SHORT_DATETIME_FORMAT: "Y-m-d H:i" diff --git a/kubernetes/netbox/base/cronjob.yaml b/kubernetes/netbox/base/cronjob.yaml index 33f1bd36..736b761d 100644 --- a/kubernetes/netbox/base/cronjob.yaml +++ b/kubernetes/netbox/base/cronjob.yaml @@ -84,8 +84,8 @@ spec: subPath: "" volumes: - name: config - configMap: - name: netbox + secret: + secretName: netbox - name: secrets projected: sources: diff --git a/kubernetes/netbox/base/deployment.yaml b/kubernetes/netbox/base/deployment.yaml index f7a91e6e..9e145ecf 100644 --- a/kubernetes/netbox/base/deployment.yaml +++ b/kubernetes/netbox/base/deployment.yaml @@ -139,8 +139,8 @@ spec: memory: 512Mi volumes: - name: config - configMap: - name: netbox-config + secret: + secretName: netbox-config - name: secrets projected: sources: @@ -270,8 +270,8 @@ spec: subPath: "" volumes: - name: config - configMap: - name: netbox-config + secret: + secretName: netbox-config - name: secrets projected: sources: diff --git a/kubernetes/netbox/base/kustomization.yaml b/kubernetes/netbox/base/kustomization.yaml index f4b8494a..fe28cfd8 100644 --- a/kubernetes/netbox/base/kustomization.yaml +++ b/kubernetes/netbox/base/kustomization.yaml @@ -5,7 +5,6 @@ resources: - ./namespace.yaml - ./pdb.yaml - ./secret.yaml - - ./configmap.yaml - ./deployment.yaml - ./network-policy.yaml - ./resource-quota.yaml @@ -20,3 +19,18 @@ resources: - ./object-bucket-claim.yaml - ./velero.yaml - ./cronjob.yaml + # - ./oauth-client.yaml +generatorOptions: + disableNameSuffixHash: false # ArgoCD Garbage Collection + labels: + app.kubernetes.io/instance: netbox + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: netbox + app.kubernetes.io/version: v4.0.0 + helm.sh/chart: netbox-5.0.0-beta9 +secretGenerator: + - name: netbox-config + namespace: netbox + files: + - configs/configuration.py + - configs/netbox.yaml diff --git a/kubernetes/netbox/base/network-policy.yaml b/kubernetes/netbox/base/network-policy.yaml index 8923b8f7..35adb5d9 100644 --- a/kubernetes/netbox/base/network-policy.yaml +++ b/kubernetes/netbox/base/network-policy.yaml @@ -149,3 +149,25 @@ spec: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: netbox +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-to-openshift-ingress + namespace: netbox + annotations: + argocd.argoproj.io/sync-wave: "0" + labels: + app.kubernetes.io/instance: netbox +spec: + policyTypes: + - Egress + podSelector: + matchLabels: + app.kubernetes.io/instance: netbox + app.kubernetes.io/name: netbox + egress: + - to: + - namespaceSelector: + matchLabels: + network.openshift.io/policy-group: ingress diff --git a/kubernetes/netbox/base/oauth-client.yaml b/kubernetes/netbox/base/oauth-client.yaml new file mode 100644 index 00000000..50e194da --- /dev/null +++ b/kubernetes/netbox/base/oauth-client.yaml @@ -0,0 +1,8 @@ +kind: OAuthClient +apiVersion: oauth.openshift.io/v1 +metadata: + name: netbox +secret: test +redirectURIs: + - https://netbox.apps.okd.arthurvardevanyan.com/oauth/complete/openshift/ +grantMethod: prompt diff --git a/terraform/homelab/zitadel_netbox.tf b/terraform/homelab/zitadel_netbox.tf new file mode 100644 index 00000000..d18ea3e5 --- /dev/null +++ b/terraform/homelab/zitadel_netbox.tf @@ -0,0 +1,48 @@ +resource "zitadel_project" "netbox" { + name = "netbox" + org_id = zitadel_org.zitadel.id + project_role_assertion = false + project_role_check = false + has_project_check = false + private_labeling_setting = "PRIVATE_LABELING_SETTING_UNSPECIFIED" +} + + +resource "zitadel_application_oidc" "netbox" { + project_id = zitadel_project.netbox.id + org_id = zitadel_org.zitadel.id + + name = "netbox" + redirect_uris = [ + "https://netbox.apps.okd.arthurvardevanyan.com/oauth/complete/oidc/", + ] + response_types = ["OIDC_RESPONSE_TYPE_CODE"] + grant_types = ["OIDC_GRANT_TYPE_AUTHORIZATION_CODE"] + post_logout_redirect_uris = [] + app_type = "OIDC_APP_TYPE_WEB" + auth_method_type = "OIDC_AUTH_METHOD_TYPE_BASIC" + version = "OIDC_VERSION_1_0" + clock_skew = "0s" + dev_mode = false + access_token_type = "OIDC_TOKEN_TYPE_BEARER" + access_token_role_assertion = false + id_token_role_assertion = false + id_token_userinfo_assertion = false + additional_origins = [] +} + + + +resource "google_secret_manager_secret" "zitadel_netbox" { + project = "homelab-${local.project_id}" + secret_id = "zitadel_netbox" + + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "zitadel_netbox" { + secret = google_secret_manager_secret.zitadel_netbox.id + secret_data = zitadel_application_oidc.netbox.client_secret +}