nextcloud / helm

A community maintained helm chart for deploying Nextcloud on Kubernetes.
GNU Affero General Public License v3.0
329 stars 265 forks source link

Anyone configuring ldap and/or oidc via this helm chart? Please share your technique. #272

Closed lknite closed 2 months ago

lknite commented 2 years ago

Everytime I reinstall this app, which has been several times due to an evolving infrastructure, I have to go back in and configure ldap to gain the ability to log in. (update, i figured out a way to do it, but a bit much to maintain... see below)

I'd like to be able to configure ldap via the values.yaml file, or configure oidc to work with keycloak. Preferrably I'd like to configure oidc.

I've been able to configure all my other apps to have oidc setup with keycloak upon deployment when has been pretty awesome, always with permissions assigned via groups claims. Surely there must be a way to do this with nextcloud also.

lknite commented 2 years ago

Here's the technique I'm currently using, seems there must be a better way:

  1. via the gui install the ldap plugin
  2. via the gui configure the ldap plugin
  3. use 'k exec -it podname -- bash'
  4. modify /usr/local/etc/php/conf.d/nextcloud.ini and set 'memory_limit=512M', necessary to use occ for some reason
  5. display the ldap config with: sudo -u www-data php occ ldap:show-config
  6. copy/paste this output into a file called ldap.conf
  7. run the following powershell script to convert the ldap.conf output into occ commands:
    
    #!/opt/microsoft/powershell/7/pwsh

parse ldap.conf which is a copy/paste from the command:

sudo -u www-data php occ ldap:show-config

$lines = gc ./ldap.conf

loop through each line copying of the name/value fields

foreach ($line in $lines) {

copy off name

$name = $line.Substring(2, 29).Trim() if (($name[0] -eq '-') -or ([char]::IsUpper($name[0]))) {

"- ignore: $name"

continue

}

copy off value

$value = $line.Substring(33).Trim('|').Trim()

display copy/paste occ commands to set the value

"sudo -u www-data php occ ldap:set-config s01 $name "$value";" }

8. copy/paste the occ commands into the postStartCommand section like so:

lifecycle: postStartCommand:

lknite commented 2 years ago

As humorous as this solution is, and entertaining to watch it work perfectly, this is the sort of thing that I wouldn't want to have to maintain long term ... who knows if it would keep working through an upgrade.

For comparison, and what I'd rather be doing, here is an OIDC configuration from the helm chart for an app called harbor:

  core:
    configOverwriteJson: |
      {
        "auth_mode": "oidc_auth",
        "oidc_name": "keycloak",
        "oidc_endpoint": "https://keycloak.vc-prod.k.home.net/auth/realms/home",
        "oidc_groups_claim": "groups",
        "oidc_admin_group": "k-prod-app-harbor-admin",
        "oidc_client_id": "k.vc-prod.harbor",
        "oidc_client_secret": "<hidden>",
        "oidc_scope": "openid,email,profile,offline_access",
        "oidc_verify_cert": "false",
        "oidc_auto_onboard": "true",
        "oidc_user_claim": "preferred_username"
      }
jrester commented 1 year ago

Hi, I encountered a similar problem as you when trying to configure OIDC and found a solution by dynamically injecting the configuration using an initContainer. I use this approach because it allowed me to use Kubernetes secrets to store the client id and client secrets (might not be required in your setup). Furthermore, I also employ terraform for managing my infrastructure, so you might need to adjust this to fit your setup.

The approach boils down to:

Below is an expert from my terraform code:

locals {
  nextcloud_oidc_config_php = <<OIDC-CONFIG
<?php
\$CONFIG = array(
  'oidc_login_provider_url' => 'xxx',
  'oidc_login_auto_redirect' => false,
  'oidc_login_client_id' => '$OIDC_CLIENT_ID',
  'oidc_login_client_secret' => '$OIDC_CLIENT_SECRET',
  'oidc_login_disable_registration' => false,
  'oidc_login_scope' => 'openid profile email',
  'oidc_login_hide_password_form' => true,
  'oidc_login_webdav_enabled' => true,
);
OIDC-CONFIG
}
...
Here would be other configuration
below is the relevant section for the values of the helm chart
...
      # The OAuth2 credentials are only available through K8S secrets, but nextcloud requires the values
      # to be present in one of it's php config files.
      # So, to get the credentials there, this init container will create the php config file
      # by interpolating the credentials from environment variables.
      # The created config file can than later be mounted and used by the nextcloud container
      extraInitContainers = [{
        name  = "nextcloud-oauth2-secret-injector"
        image = "busybox"
        volumeMounts = [{
          mountPath = "/config"
          name      = "nextcloud-config-oidc"
        }]
        env = [{
          name = "OIDC_CLIENT_ID"
          valueFrom = {
            secretKeyRef = {
              name = module.oidc_client.secret_name
              key  = "client_id"
            }
          }
          }, {
          name = "OIDC_CLIENT_SECRET"
          valueFrom = {
            secretKeyRef = {
              name = module.oidc_client.secret_name
              key  = "client_secret"
            }
          }
        }]
        command = ["/bin/sh"]
        args = [
          "-c",
          "echo -e \"${local.nextcloud_oidc_config_php}\" > /config/oidc.config.php"
        ]
      }]
      extraVolumeMounts = [{
        # Mount the OIDC config we created using the initContainer
        name      = "nextcloud-config-oidc"
        mountPath = "/var/www/html/config/oidc.config.php"
        subPath   = "oidc.config.php"
      }]
      extraVolumes = [{
        # Create a volume in memory containing the oidc config
        name = "nextcloud-config-oidc"
        emptyDir = {
          medium = "Memory"
        }
      }]

Note: You still need to manually install the OIDC app. I am still looking for a solution for this

I hope this helps!

QuinnBast commented 11 months ago

It would be nice if LDAP supported the same style of configuration through php files that OIDC supports...

I am currently fighting with @lknite's solution but my postStart command is failing and I don't know how to debug it... I would prefer to not have to manually configure LDAP in the GUI every time I start a Nextcloud instance

Also, sudo -u www-data seems to not work for me in the nextcloud container either...

# sudo -u www-data php occ
bash: sudo: command not found
wrenix commented 11 months ago

i start using the saml for get also quota from my idp. Sadly, they do not publish doku for environment variable setup (https://github.com/nextcloud/user_saml/issues/780), so create an init with an occ script

wrenix commented 11 months ago

@QuinnBast you should use su like here documentated: https://github.com/nextcloud/helm/tree/main/charts/nextcloud#running-occ-commands

QuinnBast commented 11 months ago

Thanks @wrenix! That worked great. For posterity, here's what I ended up with:

lifecycle:
  postStartCommand:
    - su
    - -s
    - /bin/sh
    - www-data
    - -c
    - |-
      echo "Configuring Nextcloud Apps"
      php occ app:enable user_ldap
      php occ app:disable firstrunwizard
      php occ app:disable sharebymail
      php occ app:disable survey_client
      php occ ldap:create-empty-config
      php occ ldap:set-config s01 hasMemberOfFilterSupport ""
      # Etc....

LDAP/AD is now integrated on initial installations :)

jessebot commented 11 months ago

For OIDC, I'm using Zitadel, an open source and self hosted identity management platform with built in OIDC capabilities, it's very similar to Keycloak, but more modern. I use the pulsejet/nextcloud-oidc-login nextcloud app and I provide these environment variables (so they can come from an existing k8s secret instead of being plain text) and config file to the helm chart values:

nextcloud:
  extraEnv:
    # OIDC parameters
    - name: "NC_oidc_login_provider_url"
      valueFrom:
        secretKeyRef:
          name: nextcloud-oidc-credentials
          key: issuer

    - name: "NC_oidc_login_client_id"
      valueFrom:
        secretKeyRef:
          name: nextcloud-oidc-credentials
          key: client_id

    - name: "NC_oidc_login_client_secret"
      valueFrom:
        secretKeyRef:
          name: nextcloud-oidc-credentials
          key: client_secret

  configs:
    oidc.config.php: |-
      <?php
      $CONFIG = array (
        // Some Nextcloud options that might make sense here
        'allow_user_to_change_display_name' => true,
        'lost_password_link' => 'disabled',

        // Automatically redirect the login page to the provider
        'oidc_login_auto_redirect' => false,

        // Redirect to this page after logging out the user
        'oidc_login_logout_url' => 'cloud.buildstars.online',

        // If set to true the user will be redirected to the
        // logout endpoint of the OIDC provider after logout
        'oidc_login_end_session_redirect' => false,

        // Login button text
        'oidc_login_button_text' => 'Log in with ZITADEL',

        // Hide the NextCloud password change form.
        'oidc_login_hide_password_form' => false,

        // Use ID Token instead of UserInfo
        'oidc_login_use_id_token' => false,

        // Attribute map for OIDC response. 
        'oidc_login_attributes' => array (
            'id' => 'preferred_username',
            'name' => 'name',
            'mail' => 'email',
            'login_filter' => 'groups',
            'photoURL' => 'picture',
            'is_admin' => 'groups_nextcloud_admins',
        ),

        // Allow only users in configured value(s) to access Nextcloud. In case the user
        // is not assigned to this value (read from oidc_login_attributes) the login
        // will not be allowed for this user.
        'oidc_login_filter_allowed_values' => array('nextcloud_admins', 'nextcloud_users'),

        // Set OpenID Connect scope
        'oidc_login_scope' => 'openid profile email',

        // Run in LDAP proxy mode
        'oidc_login_proxy_ldap' => false,

        // Disable creation of users new to Nextcloud from OIDC login.
        // A user may be known to the IdP but not (yet) known to Nextcloud.
        'oidc_login_disable_registration' => false,

        // Fallback to direct login if login from OIDC fails
        // Note that no error message will be displayed if enabled
        'oidc_login_redir_fallback' => false,

        // If you get your groups from the oidc_login_attributes, you might want
        // to create them if they are not already existing, Default is `false`.
        'oidc_create_groups' => false,

        // Enable use of WebDAV via OIDC bearer token.
        'oidc_login_webdav_enabled' => false,

        // Enable authentication with user/password for DAV clients that do not
        // support token authentication (e.g. DAVx⁵)
        'oidc_login_password_authentication' => true,

        // The time in seconds used to cache public keys from provider.
        // The default value is 1 day.
        'oidc_login_public_key_caching_time' => 86400,

        // The time in seconds used to cache the OIDC well-known configuration from the provider.
        // The default value is 1 day.
        'oidc_login_well_known_caching_time' => 86400,

        // If true, nextcloud will download user avatars on login.
        // This may lead to security issues as the server does not control
        // which URLs will be requested. Use with care.
        'oidc_login_update_avatar' => false,

        // Code challenge method for PKCE flow.
        'oidc_login_code_challenge_method' => 'S256',
        );

The only issue is the app itself, which I currently install via an occ command in a python script, but it would be nice to have default apps installed at run time. Maybe we could have an optional init container that uses occ to install a list of apps? We could takes something in values.yaml like:

nextcloud:
  apps:
    - oidc-login
    - deck
    - notes
    - bookmarks

And then in the init container command, we just need to run something like this (untested) for the command:

{{- if .Values.nextcloud.apps }}
{{- range .Values.nextcloud.apps }}
su -s /bin/sh www-data -c "php occ app:install {{ . }}"
{{- end }}  
{{- end }}

Update

@QuinnBast I just read your comment, and that is 100% what I'm gonna do now :D I will also try to put something in the README to show others :)

jessebot commented 2 months ago

As nothing is broken, I'm going to convert this to a discussion so that others can still update this with new apps and methods over time. :)