freephile / meza

Setup an enterprise MediaWiki server with simple commands
MIT License
0 stars 0 forks source link

Upgrade Meza SAML auth #74

Closed freephile closed 7 months ago

freephile commented 7 months ago

Meza uses a special setup for SAML authentication. Rather than put it into 'core' extensions and handle it like any other set of MediaWiki extensions, the instructions have you put configs into 'secret' and 'public' sections, and deploy. The deploy detects these configurations and ensures installation of extension:PluggableAuth as well as extension:SimpleSAMLPhp and the underlying simpleSAMLphp library.

And, the SAML authentication is used or leveraged beyond just the MediaWiki app to encompass the whole Webserver (Apache and HAProxy load balancer), so you'll find a class to extend simpleSAMLPhp src/roles/saml/templates/NonMediaWikiSimpleSamlAuth.php.j2

The requirements for SAML authentication for MediaWiki 1.39 mean upgrading the whole stack:

component MediaWiki 1.35.x MediaWiki 1.39.x
Extension PluggableAuth 6.3 7.0
Extension SimpleSAMLphp 5.01 7.0
library simpleSAMLphp 1.19.7 2.2.1
PHP 7.4 8.1.27
freephile commented 7 months ago

✅ (we got this into the release) There's already a new simpleSAMLphp v 2.2.1 (released 5 days ago)

freephile commented 7 months ago

I added php-sodium to meet the prerequisites

freephile commented 7 months ago

Screenshot of the Admin page

image

freephile commented 7 months ago

See docs for Service Provider configuration https://simplesamlphp.org/docs/stable/simplesamlphp-sp.html

We used 'Mock SAML.com' as a test IdP

freephile commented 7 months ago

You may need to add a certificate and a key (info added to the authsources template) 'privatekey' => 'private.pem', 'certificate' => 'public.crt',

In LocalSettings.php, your config might look like this for MockSAML.com (details and defaults added to LocalSettings.php.j2)

$wgPluggableAuth_Config['Log in using SAML'] = [
    'plugin' =>   'SimpleSAMLphp',
    'data'   => [ 'authSourceId'      => 'default-sp',
                  'usernameAttribute' => 'email',
                  'realNameAttribute' => ['firstName', 'lastName'],
                  'emailAttribute'    => 'email'
                ]
];

For the saml20-idp-remote.php.j2 template which produces the file by the same name in the simplesamlphp/metadata directory, the contents can be autogenerated by the SimpleSAMLphp Admin interface tool XML to SimpleSAMLphp metadata converter (found in the 'Federation' tab at /simplesaml/admin).

For the example of mocksaml.com, copy the XML at https://mocksaml.com/api/saml/metadata, or download it from the link at https://mocksaml.com/ and then use the converter tool.

For the test case of MockSAML.com, the entire file contents would look like this: (As good as the tool is, it doesn't output the opening <?php tag, so be sure to add that!)

<?php
$metadata['https://saml.example.com/entityid'] = [
    'entityid' => 'https://saml.example.com/entityid',
    'contacts' => [],
    'metadata-set' => 'saml20-idp-remote',
    'sign.authnrequest' => true,
    'SingleSignOnService' => [
        [
            'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
            'Location' => 'https://mocksaml.com/api/saml/sso',
        ],
        [
            'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
            'Location' => 'https://mocksaml.com/api/saml/sso',
        ],
    ],
    'SingleLogoutService' => [],
    'ArtifactResolutionService' => [],
    'NameIDFormats' => [
        'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
    ],
    'keys' => [
        [
            'encryption' => false,
            'signing' => true,
            'type' => 'X509Certificate',
            'X509Certificate' => 'MIIC4jCCAcoCCQC33wnybT5QZDANBgkqhkiG9w0BAQsFADAyMQswCQYDVQQGEwJVSzEPMA0GA1UECgwGQm94eUhRMRIwEAYDVQQDDAlNb2NrIFNBTUwwIBcNMjIwMjI4MjE0NjM4WhgPMzAyMTA3MDEyMTQ2MzhaMDIxCzAJBgNVBAYTAlVLMQ8wDQYDVQQKDAZCb3h5SFExEjAQBgNVBAMMCU1vY2sgU0FNTDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGfYettMsct1T6tVUwTudNJH5Pnb9GGnkXi9Zw/e6x45DD0RuRONbFlJ2T4RjAE/uG+AjXxXQ8o2SZfb9+GgmCHuTJFNgHoZ1nFVXCmb/Hg8Hpd4vOAGXndixaReOiq3EH5XvpMjMkJ3+8+9VYMzMZOjkgQtAqO36eAFFfNKX7dTj3VpwLkvz6/KFCq8OAwY+AUi4eZm5J57D31GzjHwfjH9WTeX0MyndmnNB1qV75qQR3b2/W5sGHRv+9AarggJkF+ptUkXoLtVA51wcfYm6hILptpde5FQC8RWY1YrswBWAEZNfyrR4JeSweElNHg4NVOs4TwGjOPwWGqzTfgTlECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAYRlYflSXAWoZpFfwNiCQVE5d9zZ0DPzNdWhAybXcTyMf0z5mDf6FWBW5Gyoi9u3EMEDnzLcJNkwJAAc39Apa4I2/tml+Jy29dk8bTyX6m93ngmCgdLh5Za4khuU3AM3L63g7VexCuO7kwkjh/+LqdcIXsVGO6XDfu2QOs1Xpe9zIzLpwm/RNYeXUjbSj5ce/jekpAw7qyVVL4xOyh8AtUW1ek3wIw1MJvEgEPt0d16oshWJpoS1OT8Lr/22SvYEo3EmSGdTVGgk3x3s+A0qWAqTcyjr7Q4s/GKYRFfomGwz0TZ4Iw1ZN99Mm0eo2USlSRTVl7QHRTuiuSThHpLKQQ==',
        ],
    ],
];
freephile commented 7 months ago

MockSAML.com configuration

saml20-idp-remote looks like this when generated by the simplesamlphp library's Admin Interface conversion tool (simplesaml/module.php/admin/federation/metadata-converter#converted)

$metadata['https://saml.example.com/entityid'] = [
    'entityid' => 'https://saml.example.com/entityid',
    'contacts' => [],
    'metadata-set' => 'saml20-idp-remote',
    'sign.authnrequest' => true,
    'SingleSignOnService' => [
        [
            'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
            'Location' => 'https://mocksaml.com/api/saml/sso',
        ],
        [
            'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
            'Location' => 'https://mocksaml.com/api/saml/sso',
        ],
    ],
    'SingleLogoutService' => [],
    'ArtifactResolutionService' => [],
    'NameIDFormats' => [
        'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
    ],
    'keys' => [
        [
            'encryption' => false,
            'signing' => true,
            'type' => 'X509Certificate',
            'X509Certificate' => 'MIIC4jCCAcoCCQC33wnybT5QZDANBgkqhkiG9w0BAQsFADAyMQswCQYDVQQGEwJVSzEPMA0GA1UECgwGQm94eUhRMRIwEAYDVQQDDAlNb2NrIFNBTUwwIBcNMjIwMjI4MjE0NjM4WhgPMzAyMTA3MDEyMTQ2MzhaMDIxCzAJBgNVBAYTAlVLMQ8wDQYDVQQKDAZCb3h5SFExEjAQBgNVBAMMCU1vY2sgU0FNTDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGfYettMsct1T6tVUwTudNJH5Pnb9GGnkXi9Zw/e6x45DD0RuRONbFlJ2T4RjAE/uG+AjXxXQ8o2SZfb9+GgmCHuTJFNgHoZ1nFVXCmb/Hg8Hpd4vOAGXndixaReOiq3EH5XvpMjMkJ3+8+9VYMzMZOjkgQtAqO36eAFFfNKX7dTj3VpwLkvz6/KFCq8OAwY+AUi4eZm5J57D31GzjHwfjH9WTeX0MyndmnNB1qV75qQR3b2/W5sGHRv+9AarggJkF+ptUkXoLtVA51wcfYm6hILptpde5FQC8RWY1YrswBWAEZNfyrR4JeSweElNHg4NVOs4TwGjOPwWGqzTfgTlECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAYRlYflSXAWoZpFfwNiCQVE5d9zZ0DPzNdWhAybXcTyMf0z5mDf6FWBW5Gyoi9u3EMEDnzLcJNkwJAAc39Apa4I2/tml+Jy29dk8bTyX6m93ngmCgdLh5Za4khuU3AM3L63g7VexCuO7kwkjh/+LqdcIXsVGO6XDfu2QOs1Xpe9zIzLpwm/RNYeXUjbSj5ce/jekpAw7qyVVL4xOyh8AtUW1ek3wIw1MJvEgEPt0d16oshWJpoS1OT8Lr/22SvYEo3EmSGdTVGgk3x3s+A0qWAqTcyjr7Q4s/GKYRFfomGwz0TZ4Iw1ZN99Mm0eo2USlSRTVl7QHRTuiuSThHpLKQQ==',
        ],
    ],
];

whereas Meza's template driven version looks like this:

Not far off. Notice 'certData' used by Meza instead of "X509Certificate" - It works, but I didn't look into the details of the expected/accepted schema.

<?php
/**
 * SAML 2.0 remote IdP metadata for SimpleSAMLphp.
 *
 * Remember to remove the IdPs you don't use from this file.
 *
 * See: https://simplesamlphp.org/docs/stable/simplesamlphp-reference-idp-remote
 */

$metadata['https://saml.example.com/entityid'] =

[
        'SingleSignOnService' => 'https://mocksaml.com/api/saml/sso',

        'SingleLogoutService' => 'https://mocksaml.com/api/saml/sso',

        'certData' => 'MIIC4jCCAcoCCQC33wnybT5QZDANBgkqhkiG9w0BAQsFADAyMQswCQYDVQQGEwJVSzEPMA0GA1UECgwGQm94eUhRMRIwEAYDVQQDDAlNb2NrIFNBTUwwIBcNMjIwMjI4MjE0NjM4WhgPMzAyMTA3MDEyMTQ2MzhaMDIxCzAJBgNVBAYTAlVLMQ8wDQYDVQQKDAZCb3h5SFExEjAQBgNVBAMMCU1vY2sgU0FNTDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGfYettMsct1T6tVUwTudNJH5Pnb9GGnkXi9Zw/e6x45DD0RuRONbFlJ2T4RjAE/uG+AjXxXQ8o2SZfb9+GgmCHuTJFNgHoZ1nFVXCmb/Hg8Hpd4vOAGXndixaReOiq3EH5XvpMjMkJ3+8+9VYMzMZOjkgQtAqO36eAFFfNKX7dTj3VpwLkvz6/KFCq8OAwY+AUi4eZm5J57D31GzjHwfjH9WTeX0MyndmnNB1qV75qQR3b2/W5sGHRv+9AarggJkF+ptUkXoLtVA51wcfYm6hILptpde5FQC8RWY1YrswBWAEZNfyrR4JeSweElNHg4NVOs4TwGjOPwWGqzTfgTlECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAYRlYflSXAWoZpFfwNiCQVE5d9zZ0DPzNdWhAybXcTyMf0z5mDf6FWBW5Gyoi9u3EMEDnzLcJNkwJAAc39Apa4I2/tml+Jy29dk8bTyX6m93ngmCgdLh5Za4khuU3AM3L63g7VexCuO7kwkjh/+LqdcIXsVGO6XDfu2QOs1Xpe9zIzLpwm/RNYeXUjbSj5ce/jekpAw7qyVVL4xOyh8AtUW1ek3wIw1MJvEgEPt0d16oshWJpoS1OT8Lr/22SvYEo3EmSGdTVGgk3x3s+A0qWAqTcyjr7Q4s/GKYRFfomGwz0TZ4Iw1ZN99Mm0eo2USlSRTVl7QHRTuiuSThHpLKQQ==',

];

Use the conversion tool

SimpleSAMLphp's metadata conversion tool SHOULD be used to interrogate your IdP's published metadata for values that go into Meza's public.yml file

freephile commented 7 months ago

secret.yml

---

wiki_app_fqdn: "134.209.163.205"

# The rest of the contents of this file have been omitted to focus on just the SAML related parts

#### Setup the SECRET configuration for SAML Authentication
#### Instructions at https://www.mediawiki.org/wiki/Meza/Setup_SAML_authentication
#### The mere presence of this key puts your Meza into "SAML Auth" mode
#### As of Meza 35.5.0 there is no 'undo' to get back to 'regular' Auth
#### So, only use this on a dev or test environment where you can verify it
#### before adopting it.
saml_secret:

  # A crypto salt for randomness. This should be random and unique. Use the
  # command below to generate a 32-character random string
  # tr -c -d '0-9a-zA-Z' </dev/urandom | dd bs=32 count=1 2>/dev/null;echo
  salt: zmxXmsatuLTrBYDN7qTAS4Qbw5Nhyp4G

  # A password to enter the SimpleSamlPhp web interface. Optionally use the
  # 16-character random generator below:
  # tr -c -d '0-9a-zA-Z' </dev/urandom | dd bs=16 count=1 2>/dev/null;echo
  adminpassword: worldwidewiki
freephile commented 7 months ago

public.yml

---
# Config file for putting non-secure items needed for configuration during
# deploy of the application

## The other contents of this file have been removed to focus
## on just the SAML Auth aspects

## Setup the PUBLIC configuration for SAML Authentication
## Instructions at https://www.mediawiki.org/wiki/Meza/Setup_SAML_authentication
## The mere presence of this key puts your Meza into "SAML Auth" mode
## As of Meza 35.5.0 there is no 'undo' to get back to 'regular' Auth
## So, only use this on a dev or test environment where you can verify it
## before adopting it.
saml_public:

  # SAML attribute provided by IdP (Identity Provider)
  idp_username_attr: email

  # SAML attribute provided by IdP
  idp_realname_attr: ['firstName', 'lastName']

  # SAML attribute provided by IdP
  idp_email_attr: email

  # SP (service provider) Entity ID, which should be the fully qualified
  # domain name of your application
  sp_entity_id: "{{ wiki_app_fqdn }}"

  # The format of the NameID we request from this IdP
  # MockSAML.com can use (unset) defaults
  # When the entire option or either array key is unset, the defaults are
  # transient and true respectively
  # name_id_policy: [ 'Format' => persistent, 'AllowCreate' => true ]
  # name_id_policy: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"

  # IdP (identity provider) Entity URL. Used as a unique identifier in
  # config/authsources.php
  # also used in metadata/saml20-idp-remote.php
  idp_entity_id: https://saml.example.com/entityid

  # URL of your SAML signon service
  single_sign_on_service: https://mocksaml.com/api/saml/sso

  # URL of your SAML logout service. Use signon if you don't have one.
  single_logout_service: https://mocksaml.com/api/saml/sso

  # Contact info for issues with SAML
  technicalcontact_name: Administrator
  technicalcontact_email: greg.rundlett@gmail.com

  # The PUBLIC certificate of your Identity Provider
  cert_data: >
  'MIIC4jCCAcoCCQC33wnybT5QZDANBgkqhkiG9w0BAQsFADAyMQswCQYDVQQGEwJVSzEPMA0GA1UECgwGQm94eUhRMRIwEAYDVQQDDAlNb2NrIFNBTUwwIBcNMjIwMjI4MjE0NjM4WhgPMzAyMTA3MDEyMTQ2MzhaMDIxCzAJBgNVBAYTAlVLMQ8wDQYDVQQKDAZCb3h5SFExEjAQBgNVBAMMCU1vY2sgU0FNTDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGfYettMsct1T6tVUwTudNJH5Pnb9GGnkXi9Zw/e6x45DD0RuRONbFlJ2T4RjAE/uG+AjXxXQ8o2SZfb9+GgmCHuTJFNgHoZ1nFVXCmb/Hg8Hpd4vOAGXndixaReOiq3EH5XvpMjMkJ3+8+9VYMzMZOjkgQtAqO36eAFFfNKX7dTj3VpwLkvz6/KFCq8OAwY+AUi4eZm5J57D31GzjHwfjH9WTeX0MyndmnNB1qV75qQR3b2/W5sGHRv+9AarggJkF+ptUkXoLtVA51wcfYm6hILptpde5FQC8RWY1YrswBWAEZNfyrR4JeSweElNHg4NVOs4TwGjOPwWGqzTfgTlECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAYRlYflSXAWoZpFfwNiCQVE5d9zZ0DPzNdWhAybXcTyMf0z5mDf6FWBW5Gyoi9u3EMEDnzLcJNkwJAAc39Apa4I2/tml+Jy29dk8bTyX6m93ngmCgdLh5Za4khuU3AM3L63g7VexCuO7kwkjh/+LqdcIXsVGO6XDfu2QOs1Xpe9zIzLpwm/RNYeXUjbSj5ce/jekpAw7qyVVL4xOyh8AtUW1ek3wIw1MJvEgEPt0d16oshWJpoS1OT8Lr/22SvYEo3EmSGdTVGgk3x3s+A0qWAqTcyjr7Q4s/GKYRFfomGwz0TZ4Iw1ZN99Mm0eo2USlSRTVl7QHRTuiuSThHpLKQQ=='
freephile commented 7 months ago

Update Meza's default templates for public and secret yaml

Rather than scatter instructions and templates and code between mediawiki.org and meza for accomplishing SAML Authentication in Meza, the default templates that are laid down when you first run 'getmeza.sh' should be updated to contain (commented) example sections for enabling SAML auth.

e.g. src/roles/init-controller-config/templates/public.yml.j2