Initial commit
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..07ea64a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2016 Mirantis Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..fc83783
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,26 @@
+DESTDIR=/
+SALTENVDIR=/usr/share/salt-formulas/env
+RECLASSDIR=/usr/share/salt-formulas/reclass
+FORMULANAME=$(shell grep name: metadata.yml|head -1|cut -d : -f 2|grep -Eo '[a-z0-9\-]*')
+
+all:
+ @echo "make install - Install into DESTDIR"
+ @echo "make test - Run tests"
+ @echo "make clean - Cleanup after tests run"
+
+install:
+ # Formula
+ [ -d $(DESTDIR)/$(SALTENVDIR) ] || mkdir -p $(DESTDIR)/$(SALTENVDIR)
+ cp -a $(FORMULANAME) $(DESTDIR)/$(SALTENVDIR)/
+ [ ! -d _modules ] || cp -a _modules $(DESTDIR)/$(SALTENVDIR)/
+ [ ! -d _states ] || cp -a _states $(DESTDIR)/$(SALTENVDIR)/ || true
+ # Metadata
+ [ -d $(DESTDIR)/$(RECLASSDIR)/service/$(FORMULANAME) ] || mkdir -p $(DESTDIR)/$(RECLASSDIR)/service/$(FORMULANAME)
+ cp -a metadata/service/* $(DESTDIR)/$(RECLASSDIR)/service/$(FORMULANAME)
+
+test:
+ [ ! -d tests ] || (cd tests; ./run_tests.sh)
+
+clean:
+ [ ! -d tests/build ] || rm -rf tests/build
+ [ ! -d build ] || rm -rf build
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..cd06133
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,2 @@
+salt-formula-shibboleth
+======================
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..8acdd82
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.0.1
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..a4dee23
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+salt-formula-shibboleth (0.0.1) trusty; urgency=medium
+
+ * Initial release
+
+ -- Alexander Noskov <anoskov@mirantis.com> Thu, 17 Oct 2016 23:23:41 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..a321d77
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,15 @@
+Source: salt-formula-shibboleth
+Maintainer: Alexander Noskov <anoskov@mirantis.com>
+Section: admin
+Priority: optional
+Build-Depends: salt-master, python, python-yaml, debhelper (>= 9)
+Standards-Version: 3.9.6
+Homepage: http://www.mirantis.com
+Vcs-Browser: https://github.com/Mirantis/salt-formula-shibboleth
+Vcs-Git: https://github.com/Mirantis/salt-formula-shibboleth.git
+
+Package: salt-formula-shibboleth
+Architecture: all
+Depends: ${misc:Depends}, salt-master, reclass, salt-formula-apache
+Description: shibboleth salt formula
+ Install and configure Shibboleth for SAML
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..3b2fb83
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,15 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: salt-formula-shibboleth
+Upstream-Contact:
+Source: https://github.com/Mirantis/salt-formula-shibboleth
+
+Files: *
+Copyright: 2014-2015 tcp cloud a.s.
+License: Apache-2.0
+ Copyright (C) 2014-2015 tcp cloud a.s.
+ .
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ .
+ On a Debian system you can find a copy of this license in
+ /usr/share/common-licenses/Apache-2.0.
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..503f917
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,2 @@
+README.rst
+VERSION
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..abde6ef
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,5 @@
+#!/usr/bin/make -f
+
+%:
+ dh $@
+
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/metadata.yml b/metadata.yml
new file mode 100644
index 0000000..66e04e4
--- /dev/null
+++ b/metadata.yml
@@ -0,0 +1,6 @@
+name: "shibboleth"
+version: "0.0.1"
+source: "https://github.com/Mirantis/salt-formula-shibboleth"
+dependencies:
+- name: apache
+ source: "https://github.com/tcpcloud/salt-formula-apache.git"
diff --git a/metadata/service/server/cluster.yml b/metadata/service/server/cluster.yml
new file mode 100644
index 0000000..b6de4a7
--- /dev/null
+++ b/metadata/service/server/cluster.yml
@@ -0,0 +1,11 @@
+applications:
+- shibboleth
+classes:
+- service.shibboleth.support
+parameters:
+ shibboleth:
+ server:
+ enabled: true
+ public_address: ${_param:proxy_vip_address_public}
+ idp_entity_id_url: "https://saml.example.com/oam/fed"
+ idp_metadata_url: "https://saml.example.com/oamfed/idp/metadata"
diff --git a/metadata/service/server/single.yml b/metadata/service/server/single.yml
new file mode 100644
index 0000000..1068c1d
--- /dev/null
+++ b/metadata/service/server/single.yml
@@ -0,0 +1,10 @@
+applications:
+- shibboleth
+classes:
+- service.shibboleth.support
+parameters:
+ shibboleth:
+ server:
+ enabled: true
+ idp_entity_id_url: "https://saml.example.com/oam/fed"
+ idp_metadata_url: "https://saml.example.com/oamfed/idp/metadata"
diff --git a/metadata/service/support.yml b/metadata/service/support.yml
new file mode 100644
index 0000000..b7a8d7f
--- /dev/null
+++ b/metadata/service/support.yml
@@ -0,0 +1,13 @@
+parameters:
+ shibboleth:
+ _support:
+ collectd:
+ enabled: false
+ heka:
+ enabled: false
+ sensu:
+ enabled: false
+ sphinx:
+ enabled: true
+ config:
+ enabled: true
diff --git a/shibboleth/files/attribute-map.xml b/shibboleth/files/attribute-map.xml
new file mode 100644
index 0000000..ade6943
--- /dev/null
+++ b/shibboleth/files/attribute-map.xml
@@ -0,0 +1,153 @@
+{%- from "shibboleth/map.jinja" import server with context %}
+<Attributes xmlns="urn:mace:shibboleth:2.0:attribute-map" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <!--
+ The mappings are a mix of SAML 1.1 and SAML 2.0 attribute names agreed to within the Shibboleth
+ community. The non-OID URNs are SAML 1.1 names and most of the OIDs are SAML 2.0 names, with a
+ few exceptions for newer attributes where the name is the same for both versions. You will
+ usually want to uncomment or map the names for both SAML versions as a unit.
+ -->
+
+ <!-- First some useful eduPerson attributes that many sites might use. -->
+
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonPrincipalName" id="eppn">
+ <AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
+ </Attribute>
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" id="eppn">
+ <AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
+ </Attribute>
+
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" id="affiliation">
+ <AttributeDecoder xsi:type="ScopedAttributeDecoder" caseSensitive="false"/>
+ </Attribute>
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" id="affiliation">
+ <AttributeDecoder xsi:type="ScopedAttributeDecoder" caseSensitive="false"/>
+ </Attribute>
+
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonAffiliation" id="unscoped-affiliation">
+ <AttributeDecoder xsi:type="StringAttributeDecoder" caseSensitive="false"/>
+ </Attribute>
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1" id="unscoped-affiliation">
+ <AttributeDecoder xsi:type="StringAttributeDecoder" caseSensitive="false"/>
+ </Attribute>
+
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonEntitlement" id="entitlement"/>
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" id="entitlement"/>
+
+ <!-- A persistent id attribute that supports personalized anonymous access. -->
+
+ <!-- First, the deprecated/incorrect version, decoded as a scoped string: -->
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonTargetedID" id="targeted-id">
+ <AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
+ <!-- <AttributeDecoder xsi:type="NameIDFromScopedAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/> -->
+ </Attribute>
+
+ <!-- Second, an alternate decoder that will decode the incorrect form into the newer form. -->
+ <!--
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonTargetedID" id="persistent-id">
+ <AttributeDecoder xsi:type="NameIDFromScopedAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/>
+ </Attribute>
+ -->
+
+ <!-- Third, the new version (note the OID-style name): -->
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" id="persistent-id">
+ <AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/>
+ </Attribute>
+
+ <!-- Fourth, the SAML 2.0 NameID Format: -->
+ <Attribute name="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" id="persistent-id">
+ <AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/>
+ </Attribute>
+
+ <!-- Some more eduPerson attributes, uncomment these to use them... -->
+ <!--
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonPrimaryAffiliation" id="primary-affiliation">
+ <AttributeDecoder xsi:type="StringAttributeDecoder" caseSensitive="false"/>
+ </Attribute>
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonNickname" id="nickname"/>
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonPrimaryOrgUnitDN" id="primary-orgunit-dn"/>
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonOrgUnitDN" id="orgunit-dn"/>
+ <Attribute name="urn:mace:dir:attribute-def:eduPersonOrgDN" id="org-dn"/>
+
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.5" id="primary-affiliation">
+ <AttributeDecoder xsi:type="StringAttributeDecoder" caseSensitive="false"/>
+ </Attribute>
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.2" id="nickname"/>
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.8" id="primary-orgunit-dn"/>
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.4" id="orgunit-dn"/>
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.3" id="org-dn"/>
+
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" id="assurance"/>
+
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.5.1.1" id="member"/>
+
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.6.1.1" id="eduCourseOffering"/>
+ <Attribute name="urn:oid:1.3.6.1.4.1.5923.1.6.1.2" id="eduCourseMember"/>
+ -->
+
+ <!-- Examples of LDAP-based attributes, uncomment to use these... -->
+ <!--
+ <Attribute name="urn:mace:dir:attribute-def:cn" id="cn"/>
+ <Attribute name="urn:mace:dir:attribute-def:sn" id="sn"/>
+ <Attribute name="urn:mace:dir:attribute-def:givenName" id="givenName"/>
+ <Attribute name="urn:mace:dir:attribute-def:displayName" id="displayName"/>
+ <Attribute name="urn:mace:dir:attribute-def:mail" id="mail"/>
+ <Attribute name="urn:mace:dir:attribute-def:telephoneNumber" id="telephoneNumber"/>
+ <Attribute name="urn:mace:dir:attribute-def:title" id="title"/>
+ <Attribute name="urn:mace:dir:attribute-def:initials" id="initials"/>
+ <Attribute name="urn:mace:dir:attribute-def:description" id="description"/>
+ <Attribute name="urn:mace:dir:attribute-def:carLicense" id="carLicense"/>
+ <Attribute name="urn:mace:dir:attribute-def:departmentNumber" id="departmentNumber"/>
+ <Attribute name="urn:mace:dir:attribute-def:employeeNumber" id="employeeNumber"/>
+ <Attribute name="urn:mace:dir:attribute-def:employeeType" id="employeeType"/>
+ <Attribute name="urn:mace:dir:attribute-def:preferredLanguage" id="preferredLanguage"/>
+ <Attribute name="urn:mace:dir:attribute-def:manager" id="manager"/>
+ <Attribute name="urn:mace:dir:attribute-def:seeAlso" id="seeAlso"/>
+ <Attribute name="urn:mace:dir:attribute-def:facsimileTelephoneNumber" id="facsimileTelephoneNumber"/>
+ <Attribute name="urn:mace:dir:attribute-def:street" id="street"/>
+ <Attribute name="urn:mace:dir:attribute-def:postOfficeBox" id="postOfficeBox"/>
+ <Attribute name="urn:mace:dir:attribute-def:postalCode" id="postalCode"/>
+ <Attribute name="urn:mace:dir:attribute-def:st" id="st"/>
+ <Attribute name="urn:mace:dir:attribute-def:l" id="l"/>
+ <Attribute name="urn:mace:dir:attribute-def:o" id="o"/>
+ <Attribute name="urn:mace:dir:attribute-def:ou" id="ou"/>
+ <Attribute name="urn:mace:dir:attribute-def:businessCategory" id="businessCategory"/>
+ <Attribute name="urn:mace:dir:attribute-def:physicalDeliveryOfficeName" id="physicalDeliveryOfficeName"/>
+
+ <Attribute name="urn:oid:2.5.4.3" id="cn"/>
+ <Attribute name="urn:oid:2.5.4.4" id="sn"/>
+ <Attribute name="urn:oid:2.5.4.42" id="givenName"/>
+ <Attribute name="urn:oid:2.16.840.1.113730.3.1.241" id="displayName"/>
+ <Attribute name="urn:oid:0.9.2342.19200300.100.1.3" id="mail"/>
+ <Attribute name="urn:oid:2.5.4.20" id="telephoneNumber"/>
+ <Attribute name="urn:oid:2.5.4.12" id="title"/>
+ <Attribute name="urn:oid:2.5.4.43" id="initials"/>
+ <Attribute name="urn:oid:2.5.4.13" id="description"/>
+ <Attribute name="urn:oid:2.16.840.1.113730.3.1.1" id="carLicense"/>
+ <Attribute name="urn:oid:2.16.840.1.113730.3.1.2" id="departmentNumber"/>
+ <Attribute name="urn:oid:2.16.840.1.113730.3.1.3" id="employeeNumber"/>
+ <Attribute name="urn:oid:2.16.840.1.113730.3.1.4" id="employeeType"/>
+ <Attribute name="urn:oid:2.16.840.1.113730.3.1.39" id="preferredLanguage"/>
+ <Attribute name="urn:oid:0.9.2342.19200300.100.1.10" id="manager"/>
+ <Attribute name="urn:oid:2.5.4.34" id="seeAlso"/>
+ <Attribute name="urn:oid:2.5.4.23" id="facsimileTelephoneNumber"/>
+ <Attribute name="urn:oid:2.5.4.9" id="street"/>
+ <Attribute name="urn:oid:2.5.4.18" id="postOfficeBox"/>
+ <Attribute name="urn:oid:2.5.4.17" id="postalCode"/>
+ <Attribute name="urn:oid:2.5.4.8" id="st"/>
+ <Attribute name="urn:oid:2.5.4.7" id="l"/>
+ <Attribute name="urn:oid:2.5.4.10" id="o"/>
+ <Attribute name="urn:oid:2.5.4.11" id="ou"/>
+ <Attribute name="urn:oid:2.5.4.15" id="businessCategory"/>
+ <Attribute name="urn:oid:2.5.4.19" id="physicalDeliveryOfficeName"/>
+ -->
+
+ {%- if server.attributes is defined %}
+ {%- for attribute in server.attributes %}
+ <Attribute name="{{ attribute.name }}" nameFormat="{{ attribute.name_format }}" id="{{ attribute.id }}"/>
+ {%- if not loop.last %}
+ {%- endif %}
+ {%- endfor %}
+ {%- endif %}
+
+</Attributes>
diff --git a/shibboleth/files/shibboleth2.xml b/shibboleth/files/shibboleth2.xml
new file mode 100644
index 0000000..7f0482b
--- /dev/null
+++ b/shibboleth/files/shibboleth2.xml
@@ -0,0 +1,114 @@
+{%- from "shibboleth/map.jinja" import server with context %}
+<SPConfig xmlns="urn:mace:shibboleth:2.0:native:sp:config"
+ xmlns:conf="urn:mace:shibboleth:2.0:native:sp:config"
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
+ xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
+ clockSkew="18000">
+
+ <!--
+ By default, in-memory StorageService, ReplayCache, ArtifactMap, and SessionCache
+ are used. See example-shibboleth2.xml for samples of explicitly configuring them.
+ -->
+
+ <!--
+ To customize behavior for specific resources on Apache, and to link vhosts or
+ resources to ApplicationOverride settings below, use web server options/commands.
+ See https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPConfigurationElements for help.
+
+ For examples with the RequestMap XML syntax instead, see the example-shibboleth2.xml
+ file, and the https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPRequestMapHowTo topic.
+ -->
+
+ <!-- The ApplicationDefaults element is where most of Shibboleth's SAML bits are defined. -->
+ <ApplicationDefaults entityID="http://{{ server.public_address }}:5000">
+
+ <!--
+ Controls session lifetimes, address checks, cookie handling, and the protocol handlers.
+ You MUST supply an effectively unique handlerURL value for each of your applications.
+ The value defaults to /Shibboleth.sso, and should be a relative path, with the SP computing
+ a relative value based on the virtual host. Using handlerSSL="true", the default, will force
+ the protocol to be https. You should also set cookieProps to "https" for SSL-only sites.
+ Note that while we default checkAddress to "false", this has a negative impact on the
+ security of your site. Stealing sessions via cookie theft is much easier with this disabled.
+ -->
+ <Sessions lifetime="28800" timeout="3600" relayState="ss:mem"
+ checkAddress="false" handlerSSL="false" cookieProps="http">
+
+ <!--
+ Configures SSO for a default IdP. To allow for >1 IdP, remove
+ entityID property and adjust discoveryURL to point to discovery service.
+ (Set discoveryProtocol to "WAYF" for legacy Shibboleth WAYF support.)
+ You can also override entityID on /Login query string, or in RequestMap/htaccess.
+ -->
+ <SSO entityID="{{ server.idp_entity_id_url }}" ECP="true">
+ SAML2 SAML1
+ </SSO>
+
+ <!-- SAML and local-only logout. -->
+ <Logout>SAML2 Local</Logout>
+
+ <!-- Extension service that generates "approximate" metadata based on SP configuration. -->
+ <Handler type="MetadataGenerator" Location="/Metadata" signing="false"/>
+
+ <!-- Status reporting service. -->
+ <Handler type="Status" Location="/Status" acl="127.0.0.1 ::1"/>
+
+ <!-- Session diagnostic service. -->
+ <Handler type="Session" Location="/Session" showAttributeValues="true"/>
+
+ <!-- JSON feed of discovery information. -->
+ <Handler type="DiscoveryFeed" Location="/DiscoFeed"/>
+ </Sessions>
+
+ <!--
+ Allows overriding of error template information/filenames. You can
+ also add attributes with values that can be plugged into the templates.
+ -->
+ <Errors supportContact="root@localhost"
+ helpLocation="/about.html"
+ styleSheet="/shibboleth-sp/main.css"/>
+
+ <MetadataProvider type="XML" uri="{{ server.idp_metadata_url }}"
+ backingFilePath="/etc/shibboleth/metadata.xml" reloadInterval="180000">
+ <!-- <MetadataFilter type="Signature" certificate="fedsigner.pem"/> -->
+ </MetadataProvider>
+
+ <!-- Example of locally maintained metadata. -->
+ <!--
+ <MetadataProvider type="XML" file="partner-metadata.xml"/>
+ -->
+
+ <!-- Map to extract attributes from SAML assertions. -->
+ <AttributeExtractor type="XML" validate="true" reloadChanges="false" path="attribute-map.xml"/>
+
+ <!-- Use a SAML query if no attributes are supplied during SSO. -->
+ <AttributeResolver type="Query" subjectMatch="true"/>
+
+ <!-- Default filtering policy for recognized attributes, lets other data pass. -->
+ <AttributeFilter type="XML" validate="true" path="attribute-policy.xml"/>
+
+ <!-- Simple file-based resolver for using a single keypair. -->
+ <CredentialResolver type="File" key="sp-key.pem" certificate="sp-cert.pem"/>
+
+ <!--
+ The default settings can be overridden by creating ApplicationOverride elements (see
+ the https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPApplicationOverride topic).
+ Resource requests are mapped by web server commands, or the RequestMapper, to an
+ applicationId setting.
+
+ Example of a second application (for a second vhost) that has a different entityID.
+ Resources on the vhost would map to an applicationId of "admin":
+ -->
+ <!--
+ <ApplicationOverride id="admin" entityID="https://admin.example.org/shibboleth"/>
+ -->
+ </ApplicationDefaults>
+
+ <!-- Policies that determine how to process and authenticate runtime messages. -->
+ <SecurityPolicyProvider type="XML" validate="true" path="security-policy.xml"/>
+
+ <!-- Low-level configuration about protocols and bindings available for use. -->
+ <ProtocolProvider type="XML" validate="true" reloadChanges="false" path="protocols.xml"/>
+
+</SPConfig>
diff --git a/shibboleth/init.sls b/shibboleth/init.sls
new file mode 100644
index 0000000..f908260
--- /dev/null
+++ b/shibboleth/init.sls
@@ -0,0 +1,6 @@
+{%- if pillar.shibboleth is defined %}
+include:
+{%- if pillar.shibboleth.server is defined %}
+- shibboleth.server
+{%- endif %}
+{%- endif %}
diff --git a/shibboleth/map.jinja b/shibboleth/map.jinja
new file mode 100644
index 0000000..a6a7b9f
--- /dev/null
+++ b/shibboleth/map.jinja
@@ -0,0 +1,6 @@
+{% set server = salt['grains.filter_by']({
+ 'Debian': {
+ 'pkgs': ['apache2', 'libapache2-mod-shib2'],
+ 'services': ['apache2', 'shibd']
+ },
+}, merge=pillar.shibboleth.get('server', {})) %}
diff --git a/shibboleth/server.sls b/shibboleth/server.sls
new file mode 100644
index 0000000..7a4bf7b
--- /dev/null
+++ b/shibboleth/server.sls
@@ -0,0 +1,33 @@
+{%- from "shibboleth/map.jinja" import server with context %}
+
+{%- if server.enabled %}
+
+include:
+- apache
+
+/etc/shibboleth/shibboleth2.xml:
+ file.managed:
+ - source: salt://shibboleth/files/shibboleth2.xml
+ - template: jinja
+ - require:
+ - pkg: apache_packages
+ - watch_in:
+ - service: apache_service
+ - service: shibboleth_service
+
+/etc/shibboleth/attribute-map.xml:
+ file.managed:
+ - source: salt://shibboleth/files/attribute-map.xml
+ - template: jinja
+ - require:
+ - pkg: apache_packages
+ - watch_in:
+ - service: apache_service
+ - service: shibboleth_service
+
+shibboleth_service:
+ service.running:
+ - enable: true
+ - name: shibd
+
+{%- endif %}
diff --git a/tests/pillar/shibboleth.sls b/tests/pillar/shibboleth.sls
new file mode 100644
index 0000000..be0df94
--- /dev/null
+++ b/tests/pillar/shibboleth.sls
@@ -0,0 +1,26 @@
+shibboleth:
+ server:
+ enabled: true
+ idp_entity_id_url: "https://saml.example.com/oam/fed"
+ idp_metadata_url: "https://saml.example.com/oamfed/idp/metadata"
+ attributes:
+ - name: test
+ id: test
+ name_format: urn:oasis:names:tc:SAML:2.0:attrname-format:basic
+apache:
+ server:
+ enabled: true
+ default_mpm: event
+ site:
+ keystone:
+ enabled: true
+ type: keystone
+ name: wsgi
+ host:
+ name: test
+ pkgs:
+ - apache2
+ - libapache2-mod-shib2
+ modules:
+ - wsgi
+ - shib2
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
new file mode 100755
index 0000000..3f42101
--- /dev/null
+++ b/tests/run_tests.sh
@@ -0,0 +1,162 @@
+#!/usr/bin/env bash
+
+set -e
+[ -n "$DEBUG" ] && set -x
+
+CURDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+METADATA=${CURDIR}/../metadata.yml
+FORMULA_NAME=$(cat $METADATA | python -c "import sys,yaml; print yaml.load(sys.stdin)['name']")
+
+## Overrideable parameters
+PILLARDIR=${PILLARDIR:-${CURDIR}/pillar}
+BUILDDIR=${BUILDDIR:-${CURDIR}/build}
+VENV_DIR=${VENV_DIR:-${BUILDDIR}/virtualenv}
+DEPSDIR=${BUILDDIR}/deps
+
+SALT_FILE_DIR=${SALT_FILE_DIR:-${BUILDDIR}/file_root}
+SALT_PILLAR_DIR=${SALT_PILLAR_DIR:-${BUILDDIR}/pillar_root}
+SALT_CONFIG_DIR=${SALT_CONFIG_DIR:-${BUILDDIR}/salt}
+SALT_CACHE_DIR=${SALT_CACHE_DIR:-${SALT_CONFIG_DIR}/cache}
+
+SALT_OPTS="${SALT_OPTS} --retcode-passthrough --local -c ${SALT_CONFIG_DIR}"
+
+if [ "x${SALT_VERSION}" != "x" ]; then
+ PIP_SALT_VERSION="==${SALT_VERSION}"
+fi
+
+## Functions
+log_info() {
+ echo "[INFO] $*"
+}
+
+log_err() {
+ echo "[ERROR] $*" >&2
+}
+
+setup_virtualenv() {
+ log_info "Setting up Python virtualenv"
+ virtualenv $VENV_DIR
+ source ${VENV_DIR}/bin/activate
+ pip install salt${PIP_SALT_VERSION}
+}
+
+setup_pillar() {
+ [ ! -d ${SALT_PILLAR_DIR} ] && mkdir -p ${SALT_PILLAR_DIR}
+ echo "base:" > ${SALT_PILLAR_DIR}/top.sls
+ for pillar in ${PILLARDIR}/*; do
+ state_name=$(basename ${pillar%.sls})
+ echo -e " ${state_name}:\n - ${state_name}" >> ${SALT_PILLAR_DIR}/top.sls
+ done
+}
+
+setup_salt() {
+ [ ! -d ${SALT_FILE_DIR} ] && mkdir -p ${SALT_FILE_DIR}
+ [ ! -d ${SALT_CONFIG_DIR} ] && mkdir -p ${SALT_CONFIG_DIR}
+ [ ! -d ${SALT_CACHE_DIR} ] && mkdir -p ${SALT_CACHE_DIR}
+
+ echo "base:" > ${SALT_FILE_DIR}/top.sls
+ for pillar in ${PILLARDIR}/*.sls; do
+ state_name=$(basename ${pillar%.sls})
+ echo -e " ${state_name}:\n - ${FORMULA_NAME}" >> ${SALT_FILE_DIR}/top.sls
+ done
+
+ cat << EOF > ${SALT_CONFIG_DIR}/minion
+file_client: local
+cachedir: ${SALT_CACHE_DIR}
+verify_env: False
+
+file_roots:
+ base:
+ - ${SALT_FILE_DIR}
+ - ${CURDIR}/..
+ - /usr/share/salt-formulas/env
+
+pillar_roots:
+ base:
+ - ${SALT_PILLAR_DIR}
+ - ${PILLARDIR}
+EOF
+}
+
+fetch_dependency() {
+ dep_name="$(echo $1|cut -d : -f 1)"
+ dep_source="$(echo $1|cut -d : -f 2-)"
+ dep_root="${DEPSDIR}/$(basename $dep_source .git)"
+ dep_metadata="${dep_root}/metadata.yml"
+
+ [ -d /usr/share/salt-formulas/env/${dep_name} ] && log_info "Dependency $dep_name already present in system-wide salt env" && return 0
+ [ -d $dep_root ] && log_info "Dependency $dep_name already fetched" && return 0
+
+ log_info "Fetching dependency $dep_name"
+ [ ! -d ${DEPSDIR} ] && mkdir -p ${DEPSDIR}
+ git clone $dep_source ${DEPSDIR}/$(basename $dep_source .git)
+ ln -s ${dep_root}/${dep_name} ${SALT_FILE_DIR}/${dep_name}
+
+ METADATA="${dep_metadata}" install_dependencies
+}
+
+install_dependencies() {
+ grep -E "^dependencies:" ${METADATA} >/dev/null || return 0
+ (python - | while read dep; do fetch_dependency "$dep"; done) << EOF
+import sys,yaml
+for dep in yaml.load(open('${METADATA}', 'ro'))['dependencies']:
+ print '%s:%s' % (dep["name"], dep["source"])
+EOF
+}
+
+clean() {
+ log_info "Cleaning up ${BUILDDIR}"
+ [ -d ${BUILDDIR} ] && rm -rf ${BUILDDIR} || exit 0
+}
+
+salt_run() {
+ [ -e ${VEN_DIR}/bin/activate ] && source ${VENV_DIR}/bin/activate
+ salt-call ${SALT_OPTS} $*
+}
+
+prepare() {
+ [ -d ${BUILDDIR} ] && mkdir -p ${BUILDDIR}
+
+ which salt-call || setup_virtualenv
+ setup_pillar
+ setup_salt
+ install_dependencies
+}
+
+run() {
+ for pillar in ${PILLARDIR}/*.sls; do
+ state_name=$(basename ${pillar%.sls})
+ salt_run --id=${state_name} state.show_sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
+ done
+}
+
+_atexit() {
+ RETVAL=$?
+ trap true INT TERM EXIT
+
+ if [ $RETVAL -ne 0 ]; then
+ log_err "Execution failed"
+ else
+ log_info "Execution successful"
+ fi
+ return $RETVAL
+}
+
+## Main
+trap _atexit INT TERM EXIT
+
+case $1 in
+ clean)
+ clean
+ ;;
+ prepare)
+ prepare
+ ;;
+ run)
+ run
+ ;;
+ *)
+ prepare
+ run
+ ;;
+esac