Merge pull request #7 from thedac/validation

Validation
This commit is contained in:
Ryan Beisner 2019-03-12 17:19:53 -05:00 committed by GitHub
commit 76b3bb0035
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 431 additions and 94 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
*__pycache__*
*.pyc
build
src/tests/bundles/overlays/local-charm-overlay.yaml.j2

View File

@ -19,6 +19,9 @@ implementation:
* https://github.com/UNINETT/mod_auth_mellon/blob/master/doc/user_guide/images/saml-web-sso.svg
* http://lasso.entrouvert.org/
* https://www.oasis-open.org/standards#samlv2.0
* https://docs.openstack.org/keystone/latest/admin/federation/configure_federation.html
* https://docs.openstack.org/keystone/latest/admin/federation/mellon.html
* https://docs.openstack.org/keystone/latest/admin/federation/mapping_combinations.html
# Usage
@ -38,16 +41,16 @@ In a bundle:
applications:
# ...
keystone-saml-mellon:
charm: cs:~dmitriis/keystone-saml-mellon
charm: cs:~openstack-charmers-next/keystone-saml-mellon
num_units: 0
options:
idp-name: 'myidp'
protocol-name: 'saml2'
user-facing-name: "myidp via saml2'
idp-name: 'samltest'
protocol-name: 'mapped'
user-facing-name: "samltest.id'
resources:
idp-metadata: "./FederationMetadata.xml"
idp-metadata: "./idp-metadata.xml"
sp-signing-keyinfo: "./sp-keyinfo.xml"
sp-private-key: "./mellon.pem"
sp-private-key: "./sp-private-key.pem"
relations:
# ...
- [ keystone, keystone-saml-mellon ]
@ -66,8 +69,11 @@ band, namely:
* NTP;
* idP.
On the Keystone charm side, this means that ssl_ca, ssl_cert, ssl_key,
use-https and os-public-hostname must be set.
It is highly recommend that on the OpenStack charms side SSL/TLS be
configured. We recommend deploying vault with a generated or uploaded
certificate authority and relating to all OpenStack services. Optionally,
ssl_ca, ssl_cert, and ssl_key can be configured on the OpenStack charms.
See also, [deploying vault](https://docs.openstack.org/project-deploy-guide/charm-deployment-guide/latest/app-vault.html) and [certificate lifecycle management](https://docs.openstack.org/project-deploy-guide/charm-deployment-guide/latest/app-certificate-management.html).
Several key pairs can be used in a generic SAML exchange along with
certificates containing public keys. Besides the pairs used for message-level
@ -116,17 +122,75 @@ Additionally, for successful certificate verification clocks of all parties
need to be properly synchronized which is why it is important for NTP agents
to be able to reach proper NTP servers on SP and idP.
# Configuration
Determine the Identity Provider (idP). The idP may be public and external to
your organization or a service your organization operates. It is good practice
to use the URL for the idP's metadata as the unique identifier for the idP in
the post-deployment configuration steps. For example https://samltest.id/saml/idp
Get the idP's metadata XML. This will be the resource file for idp-metdata.xml.
The XML will be unique for each idP. See example [idP metadata](https://samltest.id/saml/idp).
The XML must be generated by your idP rather than
attempting to create this document on your own.
Generate a certificate key pair for keystone as a Service Provider (SP). See
openssl document ion on how to. This certificate key pair will not be validated
so it may or may not be signed by your certificate authority.
The key PEM file is the resource file for sp-private-key.pem. The certificate
PEM data will be placed in an XML document and will become the
sp-signing-keyinfo.xml resource file.
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
<!--
Your base64 certificate *without* the header and footer.
Remove the following:
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-->
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
Set the protocol. This must match the protocol used in the post-deployment
configuration steps. We recommend the protocol "mapped."
juju config keystone-saml-mellon protocol-name=mapped
Determine and configure the NameID SAML specification(s). This is the format
for the user identification you expect to receive from the idP. Federated users
generated in the keystone database will use this NameID as the uid.
juju config keystone-saml-mellon nameid-formats="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
If proxies are invoked at any point between the idP and keystone as SP set
subject-confirmation-data-address-check to false.
juju config keystone-saml-mellon subject-confirmation-data-address-check=False
Attach resources
juju attach-resource keystone-saml-mellon idp-metadata=./idp-metadata.xml sp-private-key=./sp-private-key.pem. sp-signing-keyinfo=./sp-signing-keyinfo.xml
Get keystones SP metadata XML and exchange it with your idP
juju run --unit keystone/0 "cat /etc/apache2/mellon/sp-meta.keystone-saml-mellon.xml"
# Post-deployment Configuration
There are several post-deployment steps that have to be performed in order to
start using federated identity functionality in Keystone. They depend on the
chosen config values and also on an IDP configuration as it may put different
NameID values and attributes into SAML tokens. Token attributes are parsed by
mod_auth_mellon and are placed into WSGI environment which are used by
Keystone and they have the following format: "MELLON_<attribute_name>"
(one attribute can have multiple values in SAML). Both NameID and attribute
values can be used in mappings to map SAML token content to existing and, in
case of projects, potentially non-existing entities in Keystone database.
In addition to the above, there are several post-deployment steps that have to
be performed in order to start using federated identity functionality in
Keystone. They depend on the chosen config values and also on an IDP
configuration as it may put different NameID values and attributes into SAML
tokens. Token attributes are parsed by mod_auth_mellon and are placed into
WSGI environment which are used by Keystone and they have the following format:
"MELLON_<attribute_name>" (one attribute can have multiple values in SAML).
Both NameID and attribute values can be used in mappings to map SAML token
content to existing and, in case of projects, potentially non-existing entities
in Keystone database.
In order to take the above into account several objects need to be created:
@ -138,6 +202,11 @@ In order to take the above into account several objects need to be created:
* a mapping of NameID and SAML token attributes to Keystone entities;
* a federation protocol object.
Generate rules.json for mapping federated users into the keystone database. The
following is a simple example. Constraints can be added on the remote side. For
example group membership.
See [mapping documentation](https://docs.openstack.org/keystone/latest/admin/federation/mapping_combinations.html) upstream.
```
cat > rules.json <<EOF
[{
@ -154,7 +223,7 @@ In order to take the above into account several objects need to be created:
},
"projects": [
{
"name": "{0}",
"name": "{0}_project",
"roles": [
{
"name": "Member"
@ -167,10 +236,6 @@ In order to take the above into account several objects need to be created:
"remote": [
{
"type": "MELLON_NAME_ID"
},
{
"type": "MELLON_groups",
"any_one_of": ["openstack-users"]
}
]
}]
@ -180,15 +245,23 @@ In order to take the above into account several objects need to be created:
openstack group create federated_users --domain federated_domain
# created group id: 0427a780b34441488f064526a9890edd
openstack role add --group 0427a780b34441488f064526a9890edd --domain federated_domain Member
openstack identity provider create --remote-id https://adfs.intranet.test/adfs/services/trust myidp
openstack mapping create --rules rules.json myidp_mapping
openstack federation protocol create mapped --mapping myidp_mapping --identity-provider myidp
# Use the URL for your idP's metadata for remote-id. The name can be
# arbitrary.
openstack identity provider create --remote-id https://samltest.id/saml/idp samltest
# Use the rules.json created above.
openstack mapping create --rules rules.json samltest_mapping
# The name should be mapped or saml here and must match the configuration
# setting protocol-name. We recommend using "mapped"
openstack federation protocol create mapped --mapping samltest_mapping --identity-provider samltest
# list related projects
openstack federation project list
# Note and auto generated domain has been created. This is where auto
# generated users and projects will be created.
openstack domain list
```
# Bugs
Please report bugs on [Launchpad](https://bugs.launchpad.net/charm-keystone-saml-mellon/+filebug).
For general questions please refer to the OpenStack [Charm Guide](http://docs.openstack.org/developer/charm-guide/).
For general questions please refer to the OpenStack [Charm Guide](https://docs.openstack.org/charm-guide/latest/).

View File

@ -1,4 +1,5 @@
includes: ['layer:openstack', 'layer:leadership', 'interface:keystone-fid-service-provider', 'interface:websso-fid-service-provider', 'interface:juju-info']
repo: https://github.com/openstack-charmers/charm-keystone-saml-mellon
options:
basic:
use_venv: True

View File

@ -271,6 +271,10 @@ class KeystoneSAMLMellonCharm(charms_openstack.charm.OpenStackCharm):
SP_PRIVATE_KEY: ('options', 'sp_private_key'),
}
# Render idp-metadata.xml and sp-private-key with www-data group
# ownership.
group = 'www-data'
def configuration_complete(self):
"""Determine whether sufficient configuration has been provided
via charm config options and resources.

8
src/requirements.txt Normal file
View File

@ -0,0 +1,8 @@
pbr>=1.8.0,<1.9.0
simplejson>=2.2.0
netifaces>=0.10.4
netaddr>=0.7.12,!=0.7.16
Jinja2>=2.6 # BSD License (3 clause)
six>=1.9.0
dnspython>=1.12.0
psutil>=1.1.1,<2.0.0

View File

@ -1,33 +1,8 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
coverage>=3.6
charm-tools>=2.4.4
requests>=2.18.4
mock>=1.2
flake8>=2.2.4,<=2.4.1
os-testr>=0.4.1
charm-tools>=2.0.0
requests==2.6.0
# amulet deployment helpers
git+https://github.com/juju/charm-helpers#egg=charmhelpers
# BEGIN: Amulet OpenStack Charm Helper Requirements
# Liberty client lower constraints
amulet>=1.14.3,<2.0
bundletester>=0.6.1,<1.0
aodhclient>=0.1.0
python-barbicanclient>=4.0.1
python-ceilometerclient>=1.5.0
python-cinderclient>=1.4.0
python-designateclient>=1.5
python-glanceclient>=1.1.0
python-heatclient>=0.8.0
python-keystoneclient>=1.7.1
python-manilaclient>=1.8.1
python-neutronclient>=3.1.0
python-novaclient>=2.30.1
python-openstackclient>=1.7.0
python-swiftclient>=2.6.0
pika>=0.10.0,<1.0
distro-info
# END: Amulet OpenStack Charm Helper Requirements
# NOTE: workaround for 14.04 pip/tox
pytz
python-swiftclient
git+https://github.com/openstack-charmers/zaza.git#egg=zaza;python_version>='3.0'

View File

@ -0,0 +1 @@
bionic-queens.yaml

View File

@ -0,0 +1 @@
bionic-queens-smoke.yaml

View File

@ -0,0 +1,59 @@
series: bionic
relations:
- - keystone:shared-db
- mysql:shared-db
- - glance:shared-db
- mysql:shared-db
- - glance:identity-service
- keystone:identity-service
- - keystone
- keystone-saml-mellon
- - vault:shared-db
- mysql:shared-db
- - vault:certificates
- keystone:certificates
- - vault:certificates
- glance:certificates
- - vault:certificates
- openstack-dashboard:certificates
- - openstack-dashboard
- keystone-saml-mellon
- - keystone:websso-trusted-dashboard
- openstack-dashboard:websso-trusted-dashboard
- - openstack-dashboard:identity-service
- keystone:identity-service
applications:
mysql:
constraints: mem=3072M
charm: cs:~openstack-charmers-next/percona-cluster
num_units: 1
keystone:
series: bionic
charm: cs:~openstack-charmers-next/keystone
num_units: 1
options:
token-provider: 'fernet'
token-expiration: 60
keystone-saml-mellon:
series: bionic
charm: ../../../keystone-saml-mellon
num_units: 0
options:
idp-name: 'samltest'
protocol-name: 'mapped'
user-facing-name: "samltest.id"
subject-confirmation-data-address-check: False
nameid-formats: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
resources:
idp-metadata: "./idp-metadata.xml"
sp-signing-keyinfo: "./sp-signing-keyinfo.xml"
sp-private-key: "./sp-private-key.pem"
glance:
charm: cs:~openstack-charmers-next/glance
num_units: 1
vault:
num_units: 1
charm: cs:~openstack-charmers-next/vault
openstack-dashboard:
num_units: 1
charm: cs:~openstack-charmers-next/openstack-dashboard

View File

@ -0,0 +1,154 @@
relations:
- - nova-compute:amqp
- rabbitmq-server:amqp
- - neutron-gateway:amqp
- rabbitmq-server:amqp
- - keystone:shared-db
- mysql:shared-db
- - nova-cloud-controller:identity-service
- keystone:identity-service
- - glance:identity-service
- keystone:identity-service
- - neutron-api:identity-service
- keystone:identity-service
- - neutron-openvswitch:neutron-plugin-api
- neutron-api:neutron-plugin-api
- - neutron-api:shared-db
- mysql:shared-db
- - neutron-api:amqp
- rabbitmq-server:amqp
- - neutron-gateway:neutron-plugin-api
- neutron-api:neutron-plugin-api
- - glance:shared-db
- mysql:shared-db
- - glance:amqp
- rabbitmq-server:amqp
- - nova-cloud-controller:image-service
- glance:image-service
- - nova-compute:image-service
- glance:image-service
- - nova-cloud-controller:cloud-compute
- nova-compute:cloud-compute
- - nova-cloud-controller:amqp
- rabbitmq-server:amqp
- - nova-cloud-controller:quantum-network-service
- neutron-gateway:quantum-network-service
- - nova-compute:neutron-plugin
- neutron-openvswitch:neutron-plugin
- - neutron-openvswitch:amqp
- rabbitmq-server:amqp
- - openstack-dashboard:identity-service
- keystone:identity-service
- - openstack-dashboard:shared-db
- mysql:shared-db
- - nova-cloud-controller:shared-db
- mysql:shared-db
- - nova-cloud-controller:neutron-api
- neutron-api:neutron-api
- - cinder:image-service
- glance:image-service
- - cinder:amqp
- rabbitmq-server:amqp
- - cinder:identity-service
- keystone:identity-service
- - cinder:cinder-volume-service
- nova-cloud-controller:cinder-volume-service
- - cinder:shared-db
- mysql:shared-db
- - ntp:juju-info
- nova-compute:juju-info
- - ntp:juju-info
- neutron-gateway:juju-info
- - keystone
- keystone-saml-mellon
- - vault:shared-db
- mysql:shared-db
- - vault:certificates
- keystone:certificates
- - vault:certificates
- glance:certificates
- - vault:certificates
- openstack-dashboard:certificates
- - openstack-dashboard
- keystone-saml-mellon
- - keystone:websso-trusted-dashboard
- openstack-dashboard:websso-trusted-dashboard
- - vault:certificates
- cinder:certificates
- - vault:certificates
- neutron-api:certificates
- - vault:certificates
- nova-cloud-controller:certificates
series: bionic
services:
cinder:
charm: cs:~openstack-charmers-next/cinder
num_units: 1
options:
block-device: None
glance-api-version: 2
glance:
charm: cs:~openstack-charmers-next/glance
num_units: 1
keystone:
charm: cs:~openstack-charmers-next/keystone
num_units: 1
options:
token-provider: 'fernet'
mysql:
charm: cs:~openstack-charmers-next/percona-cluster
num_units: 1
constraints: mem=3072M
options:
innodb-buffer-pool-size: 256M
max-connections: 1000
neutron-api:
charm: cs:~openstack-charmers-next/neutron-api
num_units: 1
options:
flat-network-providers: physnet1
neutron-security-groups: true
neutron-gateway:
charm: cs:~openstack-charmers-next/neutron-gateway
num_units: 1
options:
bridge-mappings: physnet1:br-ex
neutron-openvswitch:
charm: cs:~openstack-charmers-next/neutron-openvswitch
num_units: 0
nova-cloud-controller:
charm: cs:~openstack-charmers-next/nova-cloud-controller
num_units: 1
options:
network-manager: Neutron
nova-compute:
charm: cs:~openstack-charmers-next/nova-compute
num_units: 2
options:
config-flags: default_ephemeral_format=ext4
enable-live-migration: true
enable-resize: true
migration-auth-type: ssh
ntp:
charm: cs:ntp
num_units: 0
openstack-dashboard:
charm: cs:~openstack-charmers-next/openstack-dashboard
num_units: 1
rabbitmq-server:
charm: cs:~openstack-charmers-next/rabbitmq-server
num_units: 1
vault:
num_units: 1
charm: cs:~openstack-charmers-next/vault
keystone-saml-mellon:
series: bionic
charm: ../../../keystone-saml-mellon
num_units: 0
options:
idp-name: 'samltest'
protocol-name: 'mapped'
user-facing-name: "samltest.id"
subject-confirmation-data-address-check: False
nameid-formats: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"

View File

@ -0,0 +1 @@
ha.yaml.j2

View File

@ -0,0 +1 @@
ha.yaml.j2

View File

@ -0,0 +1,26 @@
relations:
- - keystone
- keystone-hacluster
- - openstack-dashboard
- openstack-dashboard-hacluster
applications:
keystone:
num_units: 3
options:
vip: {{ OS_VIP00 }}
openstack-dashboard:
num_units: 3
options:
vip: {{ OS_VIP01 }}
keystone-hacluster:
charm: cs:~openstack-charmers-next/hacluster
num_units: 0
options:
corosync_transport: unicast
cluster_count: 3
openstack-dashboard-hacluster:
charm: cs:~openstack-charmers-next/hacluster
num_units: 0
options:
corosync_transport: unicast
cluster_count: 3

22
src/tests/tests.yaml Normal file
View File

@ -0,0 +1,22 @@
charm_name: keystone-saml-mellon
smoke_bundles:
- bionic-queens-smoke
gate_bundles:
- bionic-queens
- bionic-queens-ha
configure:
- zaza.charm_tests.vault.setup.auto_inititialize
- zaza.charm_tests.keystone.setup.add_demo_user
- zaza.charm_tests.glance.setup.add_lts_image
tests:
- zaza.charm_tests.keystone.tests.AuthenticationAuthorizationTest
target_deploy_status:
ntp:
workload-status: active
workload-status-message: "chrony: Ready"
vault:
workload-status: blocked
workload-status-message: Vault needs to be initialized
keystone-saml-mellon:
workload-status: blocked
workload-status-message: "Configuration is incomplete. idp-metadata: idp-metadata resource is not a well-formed xml file"

View File

@ -1,53 +1,63 @@
# Source charm: ./src/tox.ini
# Classic charm: ./tox.ini
# This file is managed centrally by release-tools and should not be modified
# within individual charm repos.
[tox]
envlist = pep8
envlist = pep8,py3
skipsdist = True
[testenv]
setenv = VIRTUAL_ENV={envdir}
PYTHONHASHSEED=0
AMULET_SETUP_TIMEOUT=2700
whitelist_externals = juju
passenv = HOME TERM AMULET_* CS_API_*
deps = -r{toxinidir}/test-requirements.txt
CHARM_DIR={envdir}
AMULET_SETUP_TIMEOUT=5400
install_command =
pip install --allow-unverified python-apt {opts} {packages}
pip install {opts} {packages}
commands = ostestr {posargs}
whitelist_externals = juju
passenv = HOME TERM AMULET_* CS_API_* JUJU_MODEL OS_*
deps = -r{toxinidir}/test-requirements.txt
[testenv:py3]
basepython = python3
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
[testenv:py35]
basepython = python3.5
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
[testenv:py36]
basepython = python3.6
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
[testenv:pep8]
basepython = python2.7
commands = charm-proof
[testenv:func27-noop]
# DRY RUN - For Debug
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json --test-pattern "gate-*" -n --no-destroy
[testenv:func27]
# Run all gate tests which are +x (expected to always pass)
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json --test-pattern "gate-*" --no-destroy
[testenv:func27-smoke]
# Run a specific test as an Amulet smoke test (expected to always pass)
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json gate-basic-xenial-pike --no-destroy
[testenv:func27-dfs]
# Run all deploy-from-source tests which are +x (may not always pass!)
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json --test-pattern "dfs-*" --no-destroy
[testenv:func27-dev]
# Run all development test targets which are +x (may not always pass!)
basepython = python2.7
commands =
bundletester -vl DEBUG -r json -o func-results.json --test-pattern "dev-*" --no-destroy
basepython = python3
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands = flake8 {posargs} hooks unit_tests tests actions lib
charm-proof
[testenv:venv]
basepython = python3
commands = {posargs}
[testenv:func]
basepython = python3
commands =
functest-run-suite --keep-model
[testenv:func-smoke]
basepython = python3
commands =
functest-run-suite --keep-model --smoke
[testenv:func-dev]
basepython = python3
commands =
functest-run-suite --keep-model --dev
[flake8]
ignore = E402,E226
exclude = */charmhelpers