From e4b9c641594d8ca23ec18db75fd1b5dcb2034b38 Mon Sep 17 00:00:00 2001
From: rodrigo diaz <rodrigo.leven@levvel.io>
Date: Wed, 19 Jul 2017 19:55:49 -0300
Subject: [PATCH 1/5] added kubernetes deployment and svc

---
 .../etc/docker_config/discovery_url.txt       |   1 +
 .../etc/docker_config/docker_config.sh        |  21 ++++
 .../etc/docker_config/entity_id.txt           |   1 +
 .../etc/docker_config/shibboleth2.xml         | 117 ++++++++++++++++++
 siteadmin-sp-deployment.yaml                  |  31 +++++
 siteadmin-sp-svc.yml                          |  18 +++
 upload_config.sh                              |   2 +
 7 files changed, 191 insertions(+)
 create mode 100644 container_files/etc/docker_config/discovery_url.txt
 create mode 100644 container_files/etc/docker_config/docker_config.sh
 create mode 100644 container_files/etc/docker_config/entity_id.txt
 create mode 100644 container_files/etc/docker_config/shibboleth2.xml
 create mode 100644 siteadmin-sp-deployment.yaml
 create mode 100644 siteadmin-sp-svc.yml
 create mode 100755 upload_config.sh

diff --git a/container_files/etc/docker_config/discovery_url.txt b/container_files/etc/docker_config/discovery_url.txt
new file mode 100644
index 0000000..6eec3f1
--- /dev/null
+++ b/container_files/etc/docker_config/discovery_url.txt
@@ -0,0 +1 @@
+https://service1.internet2.edu/shibboleth-ds/index.html
\ No newline at end of file
diff --git a/container_files/etc/docker_config/docker_config.sh b/container_files/etc/docker_config/docker_config.sh
new file mode 100644
index 0000000..ebf46e7
--- /dev/null
+++ b/container_files/etc/docker_config/docker_config.sh
@@ -0,0 +1,21 @@
+#/bin/sh
+entityID_file="/etc/docker_config/entity_id.txt"
+dicoveryURL_file="/etc/docker_config/discovery_url.txt"
+if [ -f $entityID_file ]; then
+    entityID=`cat $entityID_file`
+    discoveryURL=`cat $dicoveryURL_file`
+else
+    if [[ -z "${entityID}" ]]; then
+      entityID="Some default value because entityID is undefined"
+    else
+      entityID="${entityID}"
+    fi
+    if [[ -z "${discoveryURL}" ]]; then
+      discoveryURL="Some default value because discoveryURL is undefined"
+    else
+      discoveryURL="${discoveryURL}"
+    fi
+fi
+
+
+sed -e "s/\${entityID}/$entityID/"  -e "s/\${discoveryURL}/$discoveryURL/"  /etc/docker_config/shibboleth2.xml > /etc/shibboleth/shibboleth2.xml
diff --git a/container_files/etc/docker_config/entity_id.txt b/container_files/etc/docker_config/entity_id.txt
new file mode 100644
index 0000000..479e06a
--- /dev/null
+++ b/container_files/etc/docker_config/entity_id.txt
@@ -0,0 +1 @@
+https://fmdev.inc.testbed.tier.internet2.edu/shibboleth
\ No newline at end of file
diff --git a/container_files/etc/docker_config/shibboleth2.xml b/container_files/etc/docker_config/shibboleth2.xml
new file mode 100644
index 0000000..d9898e7
--- /dev/null
+++ b/container_files/etc/docker_config/shibboleth2.xml
@@ -0,0 +1,117 @@
+<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="180">
+
+    <!--
+    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="${entityID}" REMOTE_USER="eppn persistent-id targeted-id">
+
+
+	<!--
+	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 discoveryURL="${discoveryURL}" discoveryProtocol="SAMLDS">
+			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="chubing@internet2.edu"
+            helpLocation="/about.html"
+            styleSheet="/shibboleth-sp/main.css"/>
+        
+        <!-- InCommon Metadata -->
+	<MetadataProvider type="XML" validate="true"
+		uri="http://md.incommon.org/InCommon/InCommon-metadata.xml"
+              backingFilePath="federation-metadata.xml" reloadInterval="7200">
+            <MetadataFilter type="RequireValidUntil" maxValidityInterval="2419200"/>
+		<MetdataFilter type="Signature" certificate="inc-md-cert.pem"/>
+            <DiscoveryFilter type="Blacklist" matcher="EntityAttributes" trimTags="true" 
+              attributeName="http://macedir.org/entity-category"
+              attributeNameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
+              attributeValue="http://refeds.org/category/hide-from-discovery" />
+        </MetadataProvider>
+
+	<!-- Cirrus Multi-factor authentication proxy -->
+	<MetadataProvider type="XML" file="mfa-proxy.incommon.org-metdata.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/siteadmin-sp-deployment.yaml b/siteadmin-sp-deployment.yaml
new file mode 100644
index 0000000..4d14716
--- /dev/null
+++ b/siteadmin-sp-deployment.yaml
@@ -0,0 +1,31 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  labels:
+    app: siteadmin-sp
+  name: siteadmin-sp
+  namespace: siteadmin-deployment
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: siteadmin-sp
+      name: siteadmin-sp
+    spec:
+      containers:
+        - name: siteadmin-sp
+          image:  tier/siteadmin-sp
+          command: ["/opt/bin/httpd-shib-foreground"]
+          ports:
+           - containerPort: 80
+             protocol: TCP
+           - containerPort: 443
+             protocol: TCP
+          volumeMounts:
+          - name: siteadmin-sp-config
+            mountPath: /etc/docker_config
+      volumes:
+        - name: siteadmin-sp-config
+          configMap:
+            name: siteadmin-sp-config
diff --git a/siteadmin-sp-svc.yml b/siteadmin-sp-svc.yml
new file mode 100644
index 0000000..7a8acc0
--- /dev/null
+++ b/siteadmin-sp-svc.yml
@@ -0,0 +1,18 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: siteadmin-sp-svc
+  labels:
+    app: siteadmin-sp-svc
+spec:
+  ports:
+    - port: 80
+      protocol: TCP
+      targetPort: 80
+      name: http
+    - port: 443
+      protocol: TCP
+      targetPort: 443
+      name: https
+  selector:
+    app: siteadmin-sp
diff --git a/upload_config.sh b/upload_config.sh
new file mode 100755
index 0000000..1e53fa2
--- /dev/null
+++ b/upload_config.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+kubectl -n siteadmin-deployment create configmap siteadmin-sp-config --from-file=container_files/etc/docker_config

From d1b3df2b5dc1c4eb7fdb5fc20cf07dd1fa1a6502 Mon Sep 17 00:00:00 2001
From: rodrigo diaz <rodrigo.leven@levvel.io>
Date: Wed, 19 Jul 2017 20:58:36 -0300
Subject: [PATCH 2/5] fixes

---
 container_files/etc/docker_config/discovery_url.txt | 2 +-
 container_files/etc/docker_config/docker_config.sh  | 1 +
 container_files/etc/docker_config/entity_id.txt     | 2 +-
 siteadmin-sp-deployment.yaml                        | 2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/container_files/etc/docker_config/discovery_url.txt b/container_files/etc/docker_config/discovery_url.txt
index 6eec3f1..16f26d7 100644
--- a/container_files/etc/docker_config/discovery_url.txt
+++ b/container_files/etc/docker_config/discovery_url.txt
@@ -1 +1 @@
-https://service1.internet2.edu/shibboleth-ds/index.html
\ No newline at end of file
+https:\/\/service1.internet2.edu\/shibboleth-ds\/index.html
\ No newline at end of file
diff --git a/container_files/etc/docker_config/docker_config.sh b/container_files/etc/docker_config/docker_config.sh
index ebf46e7..00bb70f 100644
--- a/container_files/etc/docker_config/docker_config.sh
+++ b/container_files/etc/docker_config/docker_config.sh
@@ -19,3 +19,4 @@ fi
 
 
 sed -e "s/\${entityID}/$entityID/"  -e "s/\${discoveryURL}/$discoveryURL/"  /etc/docker_config/shibboleth2.xml > /etc/shibboleth/shibboleth2.xml
+/opt/bin/httpd-shib-foreground
diff --git a/container_files/etc/docker_config/entity_id.txt b/container_files/etc/docker_config/entity_id.txt
index 479e06a..9cdd51a 100644
--- a/container_files/etc/docker_config/entity_id.txt
+++ b/container_files/etc/docker_config/entity_id.txt
@@ -1 +1 @@
-https://fmdev.inc.testbed.tier.internet2.edu/shibboleth
\ No newline at end of file
+https:\/\/siteadmin.inc.testbed.tier.internet2.edu\/
\ No newline at end of file
diff --git a/siteadmin-sp-deployment.yaml b/siteadmin-sp-deployment.yaml
index 4d14716..e10a1c6 100644
--- a/siteadmin-sp-deployment.yaml
+++ b/siteadmin-sp-deployment.yaml
@@ -16,7 +16,7 @@ spec:
       containers:
         - name: siteadmin-sp
           image:  tier/siteadmin-sp
-          command: ["/opt/bin/httpd-shib-foreground"]
+          command: ["/bin/bash","/etc/docker_config/docker_config.sh"]
           ports:
            - containerPort: 80
              protocol: TCP

From 891a7fdc9be171cfab5587c8df3158404619255f Mon Sep 17 00:00:00 2001
From: rodrigo diaz <rodrigo.leven@levvel.io>
Date: Thu, 20 Jul 2017 20:36:13 -0300
Subject: [PATCH 3/5] added reverse proxy and ingress to siteadmin-sp

---
 container_files/etc/docker_config/docker_config.sh |  1 +
 container_files/etc/docker_config/proxy.conf       |  2 ++
 siteadmin-ingress.yaml                             | 14 ++++++++++++++
 3 files changed, 17 insertions(+)
 create mode 100644 container_files/etc/docker_config/proxy.conf
 create mode 100644 siteadmin-ingress.yaml

diff --git a/container_files/etc/docker_config/docker_config.sh b/container_files/etc/docker_config/docker_config.sh
index 00bb70f..f43fbe8 100644
--- a/container_files/etc/docker_config/docker_config.sh
+++ b/container_files/etc/docker_config/docker_config.sh
@@ -19,4 +19,5 @@ fi
 
 
 sed -e "s/\${entityID}/$entityID/"  -e "s/\${discoveryURL}/$discoveryURL/"  /etc/docker_config/shibboleth2.xml > /etc/shibboleth/shibboleth2.xml
+ln -s /etc/docker_config/proxy.conf /etc/httpd/conf.d/proxy.conf
 /opt/bin/httpd-shib-foreground
diff --git a/container_files/etc/docker_config/proxy.conf b/container_files/etc/docker_config/proxy.conf
new file mode 100644
index 0000000..e71192a
--- /dev/null
+++ b/container_files/etc/docker_config/proxy.conf
@@ -0,0 +1,2 @@
+ProxyPass        /	http://siteadmin-svc:3000/
+ProxyPassReverse /      http://siteadmin-svc:3000/
diff --git a/siteadmin-ingress.yaml b/siteadmin-ingress.yaml
new file mode 100644
index 0000000..4287aed
--- /dev/null
+++ b/siteadmin-ingress.yaml
@@ -0,0 +1,14 @@
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+  name: "siteadmin-ingress"
+  annotations:
+    zalando.org/aws-load-balancer-ssl-cert: arn:aws:acm:us-east-1:823003027569:certificate/c846f0e4-1c48-4315-9b41-cf29cd487700
+spec:
+  rules:
+  - host: "siteadmin.inc.testbed.tier.internet2.edu"
+    http:
+      paths:
+      - backend:
+          serviceName: "siteadmin-sp-svc"
+          servicePort: 80

From 78764d64166944606971816a57d2b7bedb654b80 Mon Sep 17 00:00:00 2001
From: rodrigo diaz <rodrigo.leven@levvel.io>
Date: Fri, 21 Jul 2017 12:53:00 -0300
Subject: [PATCH 4/5] changed proxy path

---
 container_files/etc/docker_config/proxy.conf | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/container_files/etc/docker_config/proxy.conf b/container_files/etc/docker_config/proxy.conf
index e71192a..0f2289b 100644
--- a/container_files/etc/docker_config/proxy.conf
+++ b/container_files/etc/docker_config/proxy.conf
@@ -1,2 +1,2 @@
-ProxyPass        /	http://siteadmin-svc:3000/
-ProxyPassReverse /      http://siteadmin-svc:3000/
+ProxyPass        /siteadmin/	http://siteadmin-svc:3000/
+ProxyPassReverse /siteadmin/    http://siteadmin-svc:3000/

From 6e4fe09527b18f4eb21fcc389e7b753ee0088541 Mon Sep 17 00:00:00 2001
From: rodrigo diaz <rodrigo.leven@levvel.io>
Date: Fri, 21 Jul 2017 15:54:19 -0300
Subject: [PATCH 5/5] added metada config

---
 .../etc/docker_config/docker_config.sh        |  1 +
 .../mfa-proxy.incommon.org-metdata.xml        | 52 +++++++++++++++++++
 2 files changed, 53 insertions(+)
 create mode 100644 container_files/etc/docker_config/mfa-proxy.incommon.org-metdata.xml

diff --git a/container_files/etc/docker_config/docker_config.sh b/container_files/etc/docker_config/docker_config.sh
index f43fbe8..d637eb0 100644
--- a/container_files/etc/docker_config/docker_config.sh
+++ b/container_files/etc/docker_config/docker_config.sh
@@ -19,5 +19,6 @@ fi
 
 
 sed -e "s/\${entityID}/$entityID/"  -e "s/\${discoveryURL}/$discoveryURL/"  /etc/docker_config/shibboleth2.xml > /etc/shibboleth/shibboleth2.xml
+cp /etc/docker_config/mfa-proxy.incommon.org-metdata.xml /etc/shibboleth/
 ln -s /etc/docker_config/proxy.conf /etc/httpd/conf.d/proxy.conf
 /opt/bin/httpd-shib-foreground
diff --git a/container_files/etc/docker_config/mfa-proxy.incommon.org-metdata.xml b/container_files/etc/docker_config/mfa-proxy.incommon.org-metdata.xml
new file mode 100644
index 0000000..ef252e2
--- /dev/null
+++ b/container_files/etc/docker_config/mfa-proxy.incommon.org-metdata.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<md:EntityDescriptor entityID="https://mfa-proxy.incommon.org/idp" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
+  <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+    <md:Extensions>
+      <mdui:UIInfo xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui">
+        <mdui:DisplayName xml:lang="en">InCommon Multifactor Authentication IdP Proxy</mdui:DisplayName>
+        <mdui:Description xml:lang="en">A SAML IdP Proxy that implements distributed Duo multifactor authentication</mdui:Description>
+      </mdui:UIInfo>
+    </md:Extensions>
+    <md:KeyDescriptor use="signing">
+      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+        <ds:X509Data>
+          <ds:X509Certificate>
+MIIEEjCCAvoCCQCunlLthlNf0DANBgkqhkiG9w0BAQUFADCByjELMAkGA1UEBhMC
+VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEDAOBgNVBAcTB09ha2xhbmQxHjAcBgNV
+BAoTFUNpcnJ1cyBJZGVudGl0eSwgSW5jLjEiMCAGA1UECxMZQ2lycnVzIElkZW50
+aXR5IE1GQSBQcm94eTElMCMGA1UEAxMcbWZhLXByb3h5LmNpcnJ1c2lkZW50aXR5
+LmNvbTEpMCcGCSqGSIb3DQEJARYac3VwcG9ydEBjaXJydXNpZGVudGl0eS5jb20w
+HhcNMTQwMzIxMTUyOTMyWhcNMzQwMzIwMTUyOTMyWjCByjELMAkGA1UEBhMCVVMx
+EzARBgNVBAgTCkNhbGlmb3JuaWExEDAOBgNVBAcTB09ha2xhbmQxHjAcBgNVBAoT
+FUNpcnJ1cyBJZGVudGl0eSwgSW5jLjEiMCAGA1UECxMZQ2lycnVzIElkZW50aXR5
+IE1GQSBQcm94eTElMCMGA1UEAxMcbWZhLXByb3h5LmNpcnJ1c2lkZW50aXR5LmNv
+bTEpMCcGCSqGSIb3DQEJARYac3VwcG9ydEBjaXJydXNpZGVudGl0eS5jb20wggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXndGfNVqaMyAYne0Bm7l8xNTZ
+WbzYmY7Ydhco/CMfOfTEYKGGv3n7o1Sozx2cEHiVAeiYNL/N8Tihp0y6Mh+dh0HQ
+wFBSbsbTGFocARVfaCoKn6p0GLaBm9I4KyTn2/U5DRJ9gcNmIkx72PHWg22Z+SCy
+K/awX90otWjVfpEYpODA4aAvZT/DeNR4gedy7kOPT2NNbpSPa33x/DyR+Ts4RQKM
+R2F50oceOajEao9DqLTaGqLKROGW1atgL6bwIn2Wbi3v86kqw2NiBdGz173XL7DK
+1KO73e9KaLG2QgdhDpBXz07oXyhfLZr/9Qh0JELDgJCCHjr3ww3NCK+m508jAgMB
+AAEwDQYJKoZIhvcNAQEFBQADggEBAIduyJXJqMSk/6g2ItBmOaox3uS4eawl0n64
+qOL+tJqbxHVw6j6GLNukQ1Tem0W9F3jblBE6CY+GOEpul4sTv7PkJ2+EoNi6j74a
+22VKbQpD/2Gk1kR+u7PWQHtRLfzmYX/ssoN4U7ekRfSZj4W/44cGka8y5fv58GpW
+H45nZwzsT3YOWrVHfSDE39SLfWDFiLmwhoKrZ6K/SVX1cIiR1LRgK1wy22hSehQD
+DXihc3A6Xw7eKGHQ1JD2t/mn2ml6DBLww94xvxkIhAvW3FCSvdMHuwLXDMG5kYbJ
+a8USrn8wzJKX8L//XJDEorAgrmS2Zn1ewmHIKrR23T7lvsjtttU=
+          </ds:X509Certificate>
+        </ds:X509Data>
+      </ds:KeyInfo>
+    </md:KeyDescriptor>
+    <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://mfa-proxy.incommon.org/idp/SLOService/HTTP-Redirect"/>
+    <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://mfa-proxy.incommon.org/idp/SSOService/HTTP-Redirect"/>
+  </md:IDPSSODescriptor>
+  <md:Organization>
+    <md:OrganizationName xml:lang="en">InCommon LLC</md:OrganizationName>
+    <md:OrganizationDisplayName xml:lang="en">InCommon Operations</md:OrganizationDisplayName>
+    <md:OrganizationURL xml:lang="en">http://www.incommon.org</md:OrganizationURL>
+  </md:Organization>
+  <md:ContactPerson contactType="technical">
+    <md:GivenName>Tech Support</md:GivenName>
+    <md:EmailAddress>techsupport@internet2.edu</md:EmailAddress>
+  </md:ContactPerson>
+</md:EntityDescriptor>