Skip to content

Commit

Permalink
first add
Browse files Browse the repository at this point in the history
  • Loading branch information
tjordan committed Apr 28, 2017
0 parents commit f23a0a0
Show file tree
Hide file tree
Showing 145 changed files with 32,257 additions and 0 deletions.
6 changes: 6 additions & 0 deletions ACCOUNTS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
List of accounts:

banderson -> sysadmin for everything. Should be able to go everywhere...but maybe not canvas?
jclark484, janderson -> log in to canvas (at least right now) TODO: get some people based on the course groups later

kbrown -> banned from the portal. (Math students and math students aren't allowed to use the portal)
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## Overview
This set of docker images supports a demonstration of the TIER architecture, and
how it can be used for role-based access control (RBAC) in a complex setting.
For more information about this demo, see
https://docs.google.com/presentation/d/1n34dLtyjMJReQ-OTDTWOJ4bFzTIJwwIRB7PPwPUCgik/edit#slide=id.g1f209ebfc7_0_0
`
The Group Docker image is based on Unicon's work, and contains a fully built Ldap, MySql, and Grouper environment. The Grouper component has the Grouper UI, Grouper Web Services, and an active Grouper Daemon which runs the Grouper Loader and PSP modules.

> This image does not follow best Docker practices. It is intended from demo/class usage. It can also be useful for use as a base image for Grouper development.
## Running

To run the demo:

```
$ [TODO: INSERT DOCKER COMPOSE COMMAND HERE]
```

You can log into the Grouper UI with "banderson/password". The account is a sysadmin. Also available is "jsmith/password", which has no explicit privs. There are lots of "user" accounts that have dumby course memberships.

TODO: change admin account to "tieradmin"?

The LDAP admin bind account is "cn=admin,dc=example,dc=edu/password". The MySql admin account is "root/<nopassword>".

## Building

From source:

```
$ ./build.sh
```

This will build each container needed.

## Authors
* James Babb (james.babb@wisc.edu)
* Tom Jordan (tom.jordan@wisc.edu)
* TIER API & Entity Registry Working Group (tier-api@internet2.edu)

* Based on Unicon Grouper Demo Container by:
* John Gasper (jgasper@unicon.net)
* David Langenberg (dlangenberg@unicon.net)

## LICENSE


17 changes: 17 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

# Build the dependency containers
docker build deps/ldap -t tier-demo-ldap
docker build deps/mysql -t tier-demo-mysql

# Build the Shib IDP
docker build shib-idp -t tier-demo-idp

# Build Grouper
docker build grouper -t tier-demo-grouper

# Build Midpoint
#docker build midpoint -t tier-demo-midpoint

# build the demo app
docker build test-app -t tier-demo-web-app
197 changes: 197 additions & 0 deletions canvas/provision_canvas.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
#!/usr/bin/perl -w
#
# provision_canvas.pl, DESCRIPTION
#
# Copyright (C) 2017 Tom Jordan
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# $Id:$
# Tom Jordan <tom.jordan@wisc.edu>

use vars qw/$VERSION $FILE/;
($VERSION) = q$Revision: 1.1 $ =~ /([\d.]+)/;
($FILE) = q$RCSfile: provision_canvas.pl,v $ =~ /^[^:]+: ([^\$]+),v $/;

use strict;
use REST::Client;
use JSON;
use Net::LDAP;
use Data::Dumper;

my $debug = 1;

my $canvas_url = "https://tier.instructure.com";
my $canvas_token = "10675~b1IIAPh31TCIBMRsmEqLUL436htu5Q7CP8JPMhRncRpKVh9uWYIDxbkCNWN7vSKD";
my $header;

$header->{'Authorization'} = "Bearer: $canvas_token";
$header->{'Content-type'} = "application/json";

my $client = REST::Client->new({
host => $canvas_url,
timeout => 10
});

# disable certificate checking
$client->getUseragent()->ssl_opts(verify_hostname => 0);
$client->getUseragent()->ssl_opts(SSL_verify_mode => "SSL_VERIFY_NONE");

my $ldap_host = "127.0.0.1";
my $ldap_admin = "cn=admin,dc=example,dc=edu";
my $ldap_password = "password";
my $course_groups_dn = "ou=groups,dc=example,dcu=edu";

my $ldap = Net::LDAP->new( $ldap_host, port => 389) or die $@;

my $mesg = $ldap->bind($ldap_admin, password => $ldap_password);


die "unable to bind to ldap: $@\n" if (!(defined($mesg)));

my $course_groups = get_course_groups($course_groups_dn);

foreach my $course_group (@$course_groups) {
print "About to process enrollments for $course_group\n" if $debug;
process_enrollments($course_group);
}


sub get_course_groups {
my $groups_dn = shift;
print "Fetching Course Groups\n" if $debug;

my @course_groups;
push @course_groups,"cn=app:canvas:users,ou=groups,dc=example,dc=edu";
push @course_groups,"cn=app:canvas:class_cs251,ou=groups,dc=example,dc=edu";
push @course_groups,"cn=app:canvas:class_cs252,ou=groups,dc=example,dc=edu";
print "Done fetching course groups\n" if $debug;
return \@course_groups;
}

sub process_enrollments {
my $course_group = shift;

print "processing enrollments for course group: $course_group\n" if $debug;

# TODO: Add the course to canvas

my $course_id = add_course_to_canvas($course_group);
print "COURSE_ID: $course_id\n" if $debug;

# TODO: Get current members
print "searching ldap for group: $course_group\n" if $debug;
$mesg = $ldap->search(base => $course_group,
filter => '(objectclass=*)');

my $entry = $mesg->entry(0);
my @members = $entry->get_value('member');

# TODO: Get user details for each member

foreach my $member (@members) {
# TODO: Validate whether or not the user needs to be added to canvas
my $member_details = get_member_details($member);
add_user_to_canvas($member_details);
# TODO: Add the users to the course
add_user_to_course($member_details,$course_group,$course_id);
}
}

sub get_member_details {
my $member_dn = shift;
print "Getting member details for $member_dn\n" if $debug;
$mesg = $ldap->search(base => $member_dn,
filter => '(objectclass=*)');
my $entry = $mesg->entry(0);

my $member_details;

# TODO: Get name and uid, and set a default password
my $uid = $entry->get_value('uid');
$member_details->{user}->{name} = $entry->get_value('cn');
$member_details->{user}->{skip_registration} = "true";
$member_details->{pseudonym}->{unique_id} = $uid."\@example.edu";
$member_details->{pseudonym}->{password} = "password";

print "Dumping user details..\n" if $debug;
print Dumper $member_details if $debug;

return $member_details;

}

sub add_user_to_canvas {
my $member_details = shift;

my $json_user = to_json($member_details);
print "Adding user: $json_user\n" if $debug;
$client->POST("/api/v1/accounts/1/users?access_token=$canvas_token",$json_user,$header);
my $response = from_json($client->responseContent());
print Dumper $response if $debug;
}

sub add_course_to_canvas {
my $course_group = shift;

print "Adding course $course_group to Canvas\n" if $debug;

my ($course_name) = ($course_group =~ m/cn=(.*),ou=groups,dc=example,dc=edu/);

print "Modified course_name: $course_name\n" if $debug;

my $course;
$course->{course}->{name} = $course_name;
my $json_course = to_json($course);
print "Adding course: $json_course\n" if $debug;
$client->POST("/api/v1/accounts/1/courses?access_token=$canvas_token",$json_course,$header);
my $response = from_json($client->responseContent());
my $course_id = $response->{id};
print "*** COURSE_ID: $course_id\n" if $debug;
print "Returning Course_ID: $course_id\n" if $debug;
return $course_id;
}

sub add_user_to_course {
my $member_details = shift;
my $course_group = shift;
my $course_id = shift;

# TODO: Get user's user_id
my $login_id = $member_details->{pseudonym}->{unique_id};
$client->GET("/api/v1/accounts/1/users?access_token=$canvas_token&search_term=$login_id");
my $response = from_json($client->responseContent());
my $user_id = @$response[0]->{id};

# TODO: Get Course ID

#my ($course_name) = ($course_group =~ m/cn=(.*),ou=groups,dc=example,dc=edu/);
#print "looking for Course Name: $course_name\n" if $debug;
#$client->GET("/api/v1/accounts/1/courses?access_token=$canvas_token&search_terms=$course_name");
#$response = from_json($client->responseContent());
#print $client->responseContent() if $debug;
#my $course_id = @$response[0]->{id};
#print "Found Course_ID: $course_id\n" if $debug;

# TODO: Add user to course
my $enrollment;
$enrollment->{enrollment}->{type} = "StudentEnrollment";
$enrollment->{enrollment}->{user_id} = $user_id;
$enrollment->{enrollment}->{enrollment_state} = "active";

my $json_enrollment = to_json($enrollment);
print "Adding enrollment: $json_enrollment\n" if $debug;
$client->POST("/api/v1/courses/$course_id/enrollments?access_token=$canvas_token",$json_enrollment,$header);
print Dumper $client->responseContent();
$response = from_json($client->responseContent());
print Dumper $response if $debug;
}

8 changes: 8 additions & 0 deletions canvas/saml_settings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
IdP Metadata URL: https://babb-www.cs.wisc.edu/tier-demo-metadata.xml
IdP Entity ID: https://localhost/idp/shibboleth
Log On URL: https://localhost/idp/profile/SAML2/Redirect/SSO
Cert Fingerprint: 67b3add4d6bd52c5d573b2843083cf39fb509a58
Login Attribute: eduPersonPrincipalName
Identifier Format: urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
Auth Context: no value
JIT Provisioning: not checked.
32 changes: 32 additions & 0 deletions deps/ldap/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
FROM ubuntu:trusty

MAINTAINER "TIER API & EntReg Working Group <tier-api@internet2.edu>"

RUN set -x; \
apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y slapd ldap-utils libnet-ldap-perl libauthen-sasl-perl libuuid-perl perl-doc \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& echo 'slapd/root_password password password' | debconf-set-selections \
&& echo 'slapd/root_password_again password password' | debconf-set-selections

COPY bootstrap /opt/bootstrap
COPY slapdconf/* /usr/local/bin/

RUN set -x; \
service slapd start \
&& mkdir -p /var/ldap/example \
&& chown -R openldap /var/ldap \
&& ldapadd -Y EXTERNAL -H ldapi:/// -f /opt/bootstrap/00_init.ldif \
&& ldapmodify -Y EXTERNAL -H ldapi:/// -f /opt/bootstrap/10_groupOfUniqueNames.ldif \
&& ldapmodify -Y EXTERNAL -H ldapi:/// -f /opt/bootstrap/15_groupOfNames.ldif \
&& ldapadd -Y EXTERNAL -H ldapi:/// -f /opt/bootstrap/20_eduperson_schema.ldif \
&& ldapadd -H ldapi:/// -f /opt/bootstrap/30_users.ldif -x -D "cn=admin,dc=example,dc=edu" -w password 1>/dev/null \
&& openldap_midpoint.sh \
&& service slapd stop

EXPOSE 389

VOLUME ["/etc/ldap", "/var/lib/ldap"]

CMD ["slapd", "-d", "32768", "-u", "openldap", "-g", "openldap"]
21 changes: 21 additions & 0 deletions deps/ldap/bootstrap/00_init.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
dn: olcDatabase=hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: hdb
olcDbDirectory: /var/ldap/example
olcSuffix: dc=example,dc=edu
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=example,dc=edu" write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by dn="cn=admin,dc=example,dc=edu" write by * read
olcLastMod: TRUE
olcRootDN: cn=admin,dc=example,dc=edu
olcRootPW: password
olcDbCheckpoint: 512 30
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbIndex: objectClass eq
olcDbIndex: uid eq


9 changes: 9 additions & 0 deletions deps/ldap/bootstrap/10_groupOfUniqueNames.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
dn: cn={0}core,cn=schema,cn=config
changetype: modify
delete: olcObjectClasses
olcObjectClasses: ( 2.5.6.17 NAME 'groupOfUniqueNames' DESC 'RFC2256: a group of unique names (DN and Unique Identifier)' SUP top STRUCTURAL MUST ( uniqueMember $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
-
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.17 NAME 'groupOfUniqueNames' DESC 'RFC2256: a group of unique names (DN and Unique Identifier)' SUP top STRUCTURAL MUST cn MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description $ uniqueMember ) )


8 changes: 8 additions & 0 deletions deps/ldap/bootstrap/15_groupOfNames.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
dn: cn={0}core,cn=schema,cn=config
changetype: modify
delete: olcObjectClasses
olcObjectClasses: ( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of names (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
-
add: olcObjectClasses
olcObjectClasses: ( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of names (DNs)' SUP top STRUCTURAL MUST cn MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description $ member) )

44 changes: 44 additions & 0 deletions deps/ldap/bootstrap/20_eduperson_schema.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
dn: cn=eduPerson,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: eduPerson
olcAttributeTypes: {0}( 1.3.6.1.4.1.5923.1.1.1.1 NAME 'eduPersonAffiliation' D
ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYNTAX 1
.3.6.1.4.1.1466.115.121.1.15 )
olcAttributeTypes: {1}( 1.3.6.1.4.1.5923.1.1.1.2 NAME 'eduPersonNickname' DESC
'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SUBSTR caseI
gnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
olcAttributeTypes: {2}( 1.3.6.1.4.1.5923.1.1.1.3 NAME 'eduPersonOrgDN' DESC 'e
duPerson per Internet2 and EDUCAUSE' EQUALITY distinguishedNameMatch SYNTAX 1
.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
olcAttributeTypes: {3}( 1.3.6.1.4.1.5923.1.1.1.4 NAME 'eduPersonOrgUnitDN' DES
C 'eduPerson per Internet2 and EDUCAUSE' EQUALITY distinguishedNameMatch SYNT
AX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {4}( 1.3.6.1.4.1.5923.1.1.1.5 NAME 'eduPersonPrimaryAffilia
tion' DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SY
NTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
olcAttributeTypes: {5}( 1.3.6.1.4.1.5923.1.1.1.6 NAME 'eduPersonPrincipalName'
DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYNTAX
1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
olcAttributeTypes: {6}( 1.3.6.1.4.1.5923.1.1.1.7 NAME 'eduPersonEntitlement' D
ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseExactMatch SYNTAX 1.3
.6.1.4.1.1466.115.121.1.15 )
olcAttributeTypes: {7}( 1.3.6.1.4.1.5923.1.1.1.8 NAME 'eduPersonPrimaryOrgUnit
DN' DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY distinguishedNameMat
ch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
olcAttributeTypes: {8}( 1.3.6.1.4.1.5923.1.1.1.9 NAME 'eduPersonScopedAffiliat
ion' DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYN
TAX 1.3.6.1.4.1.1466.115.121.1.15 )
olcAttributeTypes: {9}( 1.3.6.1.4.1.5923.1.1.1.10 NAME 'eduPersonTargetedID' D
ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYNTAX 1.
3.6.1.4.1.1466.115.121.1.15 )
olcAttributeTypes: {10}( 1.3.6.1.4.1.5923.1.1.1.11 NAME 'eduPersonAssurance' D
ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYNTAX 1.
3.6.1.4.1.1466.115.121.1.15 )
olcAttributeTypes: {11}( 1.3.6.1.4.1.5923.1.1.1.12 NAME 'grouperMemberOf' D
ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYNTAX 1.3
.6.1.4.1.1466.115.121.1.15 )
olcObjectClasses: {0}( 1.3.6.1.4.1.5923.1.1.2 NAME 'eduPerson' DESC 'eduPerson
per Internet2 and EDUCAUSE' AUXILIARY MAY ( eduPersonAffiliation $ eduPerson
Nickname $ eduPersonOrgDN $ eduPersonOrgUnitDN $ eduPersonPrimaryAffiliation
$ eduPersonPrincipalName $ eduPersonEntitlement $ eduPersonPrimaryOrgUnitDN $
eduPersonScopedAffiliation $ eduPersonTargetedID $ eduPersonAssurance $ grouperMemberOf ) )
Loading

0 comments on commit f23a0a0

Please sign in to comment.