update-metadata.php 6.71 KB
Newer Older
1 2 3 4
<?php // Copyright (c) 2018, SWITCH
$MAN=<<<PAGE
Name:        SWITCHwayf
Author:      Lukas Haemmerle, SWITCH
Guillaume Rousse's avatar
Guillaume Rousse committed
5
Description: This script is used to dynamically create the list of
6 7
             IdPs and SP to be displayed for the WAYF/DS service 
             based on the federation metadata.
Guillaume Rousse's avatar
Guillaume Rousse committed
8
             It is intended to be run periodically, e.g. with a cron
9
             entry like:
Guillaume Rousse's avatar
Guillaume Rousse committed
10 11 12 13 14
             5 * * * * /usr/bin/php update-metadata.php \
                 --metadata-file /var/cache/shibboleth/metadata.switchaai.xml \
                 --metadata-idp-file /tmp/IDProvider.metadata.php \
                 --metadata-sp-file /tmp/SProvider.metadata.php \
                 > /dev/null
15
        
Guillaume Rousse's avatar
Guillaume Rousse committed
16 17
Usage
-----
18 19 20
php update-metadata.php -help|-h
php update-metadata.php --metadata-file <file> \
    --metadata-idp-file <file> --metadata-sp-file <file> \
21
    [--verbose | -v] [--min-sp-count <count>] [--min-idp-count <count>]
22 23
php update-metadata.php --metadata-url <url> \
    --metadata-idp-file <file> --metadata-sp-file <file> \
24
    [--verbose | -v] [--min-sp-count <count>] [--min-idp-count <count>]
25

Guillaume Rousse's avatar
Guillaume Rousse committed
26 27
Argument Description
--------------------
28
--metadata-url <url>        SAML2 metadata URL
29 30 31
--metadata-file <file>      SAML2 metadata file
--metadata-idp-file <file>  File containing Service Providers 
--metadata-sp-file <file>   File containing Identity Providers 
32 33
--min-idp-count <count>     Minimum expected number of IdPs in metadata
--min-sp-count <count>      Minimum expected number of SPs in metadata
34
--language <locale>         Language locale, e.g. 'en', 'jp', ...
35 36
--syslog                    Use syslog for reporting
--syslog-prefix <prefix>    Prefix for syslog messages
37
--verbose | -v              Verbose mode
Guillaume Rousse's avatar
Guillaume Rousse committed
38
--help | -h                 Print this man page
39 40 41 42


PAGE;

Guillaume Rousse's avatar
Guillaume Rousse committed
43
$topLevelDir = dirname(__DIR__);
44 45 46

require_once($topLevelDir . '/lib/functions.php');
require_once($topLevelDir . '/lib/readMetadata.php');
47 48 49

// Script options
$longopts = array(
50
    "metadata-url:",
51 52 53
    "metadata-file:",
    "metadata-idp-file:",
    "metadata-sp-file:",
54 55
    "min-idp-count:",
    "min-sp-count:",
56 57
    "language:",
    "verbose",
58 59
    "syslog",
    "syslog-prefix:",
60 61 62 63 64 65 66 67 68
    "help",
);

$options = getopt('hv', $longopts);

if (isset($options['help']) || isset($options['h'])) {
	exit($MAN);
} 

69 70 71 72 73 74
// simple options
$language = isset($options['language']) ? $options['language'] : 'en';
$verbose  = isset($options['verbose']) || isset($options['v']) ? true : false;
$syslog   = isset($options['syslog']) ? true : false;
$prefix   = isset($options['syslog-prefix']) ? $options['syslog-prefix'] : 'switchwayf';

75 76 77
if (isset($options['metadata-url'])) {
	$metadataURL = $options['metadata-url'];
} elseif (isset($options['metadata-file'])) {
78
	$metadataFile = $options['metadata-file'];
79
} else {
80
	reportError("Exiting: both --metadata-url and --metadata-file parameters missing\n");
81
	exit(1);
82 83 84
}

if (!isset($options['metadata-sp-file'])) {
85
	reportError("Exiting: mandatory --metadata-sp-file parameter missing\n");
86
	exit(1);
87 88 89 90 91 92
} else {
	$metadataSPFile = $options['metadata-sp-file'];
	$metadataTempSPFile = $metadataSPFile.'.swp';
}

if (!isset($options['metadata-idp-file'])) {
93
	reportError("Exiting: mandatory --metadata-idp-file parameter missing\n");
94
	exit(1);
95 96 97 98 99
} else {
	$metadataIDPFile = $options['metadata-idp-file'];
	$metadataTempIDPFile = $metadataIDPFile.'.swp';
}

100 101
if (isset($options['min-sp-count'])) {
	if (!is_numeric($options['min-sp-count'])) {
102
		reportError("Exiting: invalid value for --min-sp-count parameter\n");
103
		exit(1);
104 105 106 107 108 109 110 111 112
	} else {
		$minSPCount = $options['min-sp-count'];
	}
} else {
	$minSPCount = 0;
}

if (isset($options['min-idp-count'])) {
	if (!is_numeric($options['min-idp-count'])) {
113
		reportError("Exiting: invalid value for --min-idp-count parameter\n");
114
		exit(1);
115 116 117 118 119 120 121
	} else {
		$minIDPCount = $options['min-idp-count'];
	}
} else {
	$minIDPCount = 0;
}

122
// Input validation
123 124 125
if ($metadataURL) {
	$metadataFile = tempnam(sys_get_temp_dir(), 'metadata');
	if (!ini_get('allow_url_fopen')) {
126
		reportError("Exiting: allow_url_fopen disabled, unabled to download $metadataURL\n");
127
		exit(1);
128 129
	}
	if ($verbose) {
130
		reportInfo("Downloading metadata from $metadataURL to $metadataFile\n");
131
	}
132
	$result = @copy($metadataURL, $metadataFile);
133 134
	if (!$result) {
		$error = error_get_last();
135
		$message = explode(': ', $error['message'])[2];
136
		reportError("Exiting: could not download $metadataURL: $message");
137
		exit(1);
138 139 140 141 142 143
	}
} else {
	if (
		!file_exists($metadataFile)
		|| filesize($metadataFile) == 0
		) {
144
		reportError("Exiting: file $metadataFile is empty or does not exist\n");
145
		exit(1);
146 147 148
	}

	if (!is_readable($metadataFile)){
149
		reportError("Exiting: file $metadataFile is not readable\n");
150
		exit(1);
151
	}
152 153 154
}

if ($verbose) {
155
	reportInfo("Parsing metadata file $metadataFile\n");
156 157 158 159 160 161 162
}

// Parse metadata
list($metadataIDProviders, $metadataSProviders) = parseMetadata($metadataFile, $language);

// If $metadataIDProviders is not FALSE, dump results in $metadataIDPFile.
if (is_array($metadataIDProviders)){
163 164
	$IDPCount = count($metadataIDProviders);
	if ($IDPCount < $minIDPCount) {
165
		reportError("Exiting: number of Identity Providers found ($IDPCount) lower than expected ($minIDPCount)\n");
166
		exit(1);
167
	}
168 169

	if ($verbose) {
170
		reportInfo("Dumping $IDPCount extracted Identity Providers to file $metadataIDPFile\n");
171 172 173 174
	}
	dumpFile($metadataTempIDPFile, $metadataIDProviders, 'metadataIDProviders');
	
	if(!rename($metadataTempIDPFile, $metadataIDPFile)){
175
		reportError("Exiting: could not rename temporary file $metadataTempIDPFile to $metadataIDPFile\n");
176
		exit(1);
177 178 179 180 181
	}
}

// If $metadataSProviders is not FALSE, dump results in $metadataSPFile.
if (is_array($metadataSProviders)){
182 183
	$SPCount = count($metadataSProviders);
	if ($SPCount < $minSPCount) {
184
		reportError("Exiting: number of Service Providers found ($SPCount) lower than expected ($minSPCount)\n");
185
		exit(1);
186
	}
187 188

	if ($verbose) {
189
		reportInfo("Dumping $SPCount extracted Service Providers to file $metadataSPFile\n");
190 191 192 193
	}
	dumpFile($metadataTempSPFile, $metadataSProviders, 'metadataSProviders');
	
	if(!rename($metadataTempSPFile, $metadataSPFile)){
194
		reportError("Exiting: could not rename temporary file $metadataTempSPFile to $metadataSPFile\n");
195
		exit(1);
196 197
	}
}
198 199 200

// clean up if needed
if ($metadataURL) {
201
	$result = @unlink($metadataFile);
202 203
	if (!$result) {
		$error = error_get_last();
204
		$message = $error['message'];
205
		reportError("Exiting: could not delete temporary file $metadataFile: $message");
206
		exit(1);
207 208
	}
}
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230

function reportError($message) {
	global $syslog, $prefix;

	if ($syslog) {
		openlog($prefix, LOG_NDELAY, LOG_USER);
		syslog(LOG_ERR, $message);
	} else {
		fwrite(STDERR, $message);
	}
}

function reportInfo($message) {
	global $syslog, $prefix;

	if ($syslog) {
		openlog($prefix, LOG_NDELAY, LOG_USER);
		syslog(LOG_INFO, $message);
	} else {
		fwrite(STDOUT, $message);
	}
}