Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
simplesamlphp
Manage
Activity
Members
Labels
Plan
Jira
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
Perun
Perun ProxyIdP
v1
simplesamlphp
Commits
b326e5b3
Commit
b326e5b3
authored
3 years ago
by
Tim van Dijen
Browse files
Options
Downloads
Patches
Plain Diff
Rewrite MDQ using symfony/filesystem
parent
185eeb71
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
lib/SimpleSAML/Metadata/Sources/MDQ.php
+71
-38
71 additions, 38 deletions
lib/SimpleSAML/Metadata/Sources/MDQ.php
with
71 additions
and
38 deletions
lib/SimpleSAML/Metadata/Sources/MDQ.php
+
71
−
38
View file @
b326e5b3
...
...
@@ -4,21 +4,36 @@ declare(strict_types=1);
namespace
SimpleSAML\Metadata\Sources
;
use
Exception
;
use
RobRichards\XMLSecLibs\XMLSecurityDSig
;
use
SimpleSAML\Assert\Assert
;
use
SimpleSAML\Configuration
;
use
SimpleSAML\Error
;
use
SimpleSAML\Logger
;
use
SimpleSAML\Metadata\MetaDataStorageSource
;
use
SimpleSAML\Metadata\SAMLParser
;
use
SimpleSAML\Utils
;
use
Symfony\Component\Filesystem\Filesystem
;
use
Symfony\Component\HttpFoundation\File\File
;
use
function
array_key_exists
;
use
function
error_get_last
;
use
function
is_array
;
use
function
serialize
;
use
function
sha1
;
use
function
sprintf
;
use
function
strval
;
use
function
time
;
use
function
unserialize
;
use
function
urlencode
;
/**
* This class implements SAML Metadata Query Protocol
*
* @package
S
imple
SAML
php
* @package
s
imple
samlphp/simplesaml
php
*/
class
MDQ
extends
\SimpleSAML\Metadata\
MetaDataStorageSource
class
MDQ
extends
MetaDataStorageSource
{
/**
* The URL of MDQ server (url:port)
...
...
@@ -34,7 +49,6 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
*/
private
?string
$cacheDir
;
/**
* The maximum cache length, in seconds.
*
...
...
@@ -42,6 +56,11 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
*/
private
int
$cacheLength
;
/**
* @var \Symfony\Component\Filesystem\Filesystem;
*/
private
Filesystem
$fileSystem
;
/**
* This function initializes the dynamic XML metadata source.
...
...
@@ -61,7 +80,7 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
protected
function
__construct
(
array
$config
)
{
if
(
!
array_key_exists
(
'server'
,
$config
))
{
throw
new
\
Exception
(
__CLASS__
.
": the 'server' configuration option is not set."
);
throw
new
Exception
(
__CLASS__
.
": the 'server' configuration option is not set."
);
}
else
{
$this
->
server
=
$config
[
'server'
];
}
...
...
@@ -78,6 +97,8 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
}
else
{
$this
->
cacheLength
=
86400
;
}
$this
->
fileSystem
=
new
Filesystem
();
}
...
...
@@ -120,7 +141,7 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
* @param string $set The metadata set this entity belongs to.
* @param string $entityId The entity id of this entity.
*
* @return array|
NULL
The associative array with the metadata for this entity, or NULL
* @return array|
null
The associative array with the metadata for this entity, or NULL
* if the entity could not be found.
* @throws \Exception If an error occurs while loading metadata from cache.
*/
...
...
@@ -130,41 +151,47 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
return
null
;
}
$cache
f
ile
n
ame
=
$this
->
getCacheFilename
(
$set
,
$entityId
);
if
(
!
file_
exists
(
$cache
f
ile
n
ame
))
{
$cache
F
ile
N
ame
=
$this
->
getCacheFilename
(
$set
,
$entityId
);
if
(
!
$this
->
fileSystem
->
exists
(
$cache
F
ile
N
ame
))
{
return
null
;
}
if
(
!
is_readable
(
$cachefilename
))
{
throw
new
\Exception
(
__CLASS__
.
': could not read cache file for entity ['
.
$cachefilename
.
']'
);
$file
=
new
file
(
$cacheFileName
);
if
(
!
$file
->
isReadable
())
{
throw
new
Exception
(
sprintf
(
'%s: could not read cache file for entity [%s]'
,
strval
(
$file
),
__CLASS__
));
}
Logger
::
debug
(
__CLASS__
.
'
: reading cache [
'
.
$entityId
.
'] => ['
.
$cachefilename
.
']'
);
Logger
::
debug
(
sprintf
(
'%s
: reading cache [
%s] => [%s]'
,
__CLASS__
,
$entityId
,
strval
(
$file
))
);
/* Ensure that this metadata isn't older that the cachelength option allows. This
* must be verified based on the file, since this option may be changed after the
* file is written.
*/
$stat
=
stat
(
$cachefilename
);
if
(
$stat
[
'mtime'
]
+
$this
->
cacheLength
<=
time
())
{
Logger
::
debug
(
__CLASS__
.
': cache file older that the cachelength option allows.'
);
if
((
$file
->
getMtime
()
+
$this
->
cacheLength
)
<=
time
())
{
Logger
::
debug
(
sprintf
(
'%s: cache file older that the cachelength option allows.'
,
__CLASS__
));
return
null
;
}
$rawData
=
file
_
get
_c
ontent
s
(
$cachefilename
);
$rawData
=
$
file
->
get
C
ontent
(
);
if
(
empty
(
$rawData
))
{
/** @var array $error */
$error
=
error_get_last
();
throw
new
\Exception
(
__CLASS__
.
': error reading metadata from cache file "'
.
$cachefilename
.
'": '
.
$error
[
'message'
]
);
throw
new
Exception
(
sprintf
(
'%s: error reading metadata from cache file "%s": %s'
,
__CLASS__
,
strval
(
$file
),
$error
[
'message'
],
));
}
$data
=
unserialize
(
$rawData
);
if
(
$data
===
false
)
{
throw
new
\Exception
(
__CLASS__
.
': error unserializing cached data from file "'
.
$cachefilename
.
'".'
);
throw
new
Exception
(
sprintf
(
'%s: error unserializing cached data from file "%s".'
,
__CLASS__
,
strval
(
$file
))
);
}
if
(
!
is_array
(
$data
))
{
throw
new
\
Exception
(
__CLASS__
.
'
: Cached metadata from "
'
.
$cachefilename
.
'" wasn\'t an array.'
);
throw
new
Exception
(
sprintf
(
'%s
: Cached metadata from "
%s" wasn\'t an array.'
,
__CLASS__
,
strval
(
$file
))
);
}
return
$data
;
...
...
@@ -186,12 +213,14 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
return
;
}
$cachefilename
=
$this
->
getCacheFilename
(
$set
,
$entityId
);
if
(
!
is_writable
(
dirname
(
$cachefilename
)))
{
throw
new
\Exception
(
__CLASS__
.
': could not write cache file for entity ['
.
$cachefilename
.
']'
);
$cacheFileName
=
$this
->
getCacheFilename
(
$set
,
$entityId
);
$file
=
new
File
(
$cacheFileName
);
if
(
!
$file
->
isWritable
())
{
throw
new
Exception
(
sprintf
(
'%s: could not write cache file for entity [%s]'
,
__CLASS__
,
strval
(
$file
)));
}
Logger
::
debug
(
__CLASS__
.
': Writing cache ['
.
$entityId
.
'] => ['
.
$cachefilename
.
']'
);
file_put_contents
(
$cachefilename
,
serialize
(
$data
));
Logger
::
debug
(
sprintf
(
'%s: Writing cache [%s] => [%s]'
,
__CLASS__
,
$entityId
,
strval
(
$file
)));
$this
->
fileSystem
->
appendToFile
(
strval
(
$file
),
serialize
(
$data
),
true
);
}
...
...
@@ -201,7 +230,7 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
* @param \SimpleSAML\Metadata\SAMLParser $entity A SAML2Parser representing an entity.
* @param string $set The metadata set we are looking for.
*
* @return array|
NULL
The associative array with the metadata, or NULL if no metadata for
* @return array|
null
The associative array with the metadata, or NULL if no metadata for
* the given set was found.
*/
private
static
function
getParsedSet
(
SAMLParser
$entity
,
string
$set
):
?array
...
...
@@ -214,7 +243,7 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
case
'attributeauthority-remote'
:
return
$entity
->
getAttributeAuthorities
();
default
:
Logger
::
warning
(
__CLASS__
.
'
: unknown metadata set: \'
'
.
$set
.
'\'.'
);
Logger
::
warning
(
sprintf
(
'%s
: unknown metadata set: \'
%s\'.'
,
__CLASS__
,
$set
)
);
}
return
null
;
...
...
@@ -241,12 +270,12 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
*/
public
function
getMetaData
(
string
$entityId
,
string
$set
):
?array
{
Logger
::
info
(
__CLASS__
.
'
: loading metadata entity [
'
.
$entityId
.
'] from ['
.
$set
.
']'
);
Logger
::
info
(
sprintf
(
'%s
: loading metadata entity [
%s] from [%s]'
,
__CLASS__
,
$entityId
,
$set
)
);
// read from cache if possible
try
{
$data
=
$this
->
getFromCache
(
$set
,
$entityId
);
}
catch
(
\
Exception
$e
)
{
}
catch
(
Exception
$e
)
{
Logger
::
error
(
$e
->
getMessage
());
// proceed with fetching metadata even if the cache is broken
$data
=
null
;
...
...
@@ -259,45 +288,49 @@ class MDQ extends \SimpleSAML\Metadata\MetaDataStorageSource
if
(
isset
(
$data
))
{
// metadata found in cache and not expired
Logger
::
debug
(
__CLASS__
.
'
: using cached metadata for:
'
.
$entityId
.
'.'
);
Logger
::
debug
(
sprintf
(
'%s
: using cached metadata for:
%s.'
,
__CLASS__
,
$entityId
)
);
return
$data
;
}
// look at Metadata Query Protocol: https://github.com/iay/md-query/blob/master/draft-young-md-query.txt
$mdq_url
=
$this
->
server
.
'/entities/'
.
urlencode
(
$entityId
);
Logger
::
debug
(
__CLASS__
.
'
: downloading metadata for "
'
.
$entityId
.
'" from ['
.
$mdq_url
.
']'
);
Logger
::
debug
(
sprintf
(
'%s
: downloading metadata for "
%s" from [%s]'
,
__CLASS__
,
$entityId
,
$mdq_url
)
);
$httpUtils
=
new
Utils\HTTP
();
try
{
$xmldata
=
$httpUtils
->
fetch
(
$mdq_url
);
}
catch
(
\
Exception
$e
)
{
}
catch
(
Exception
$e
)
{
// Avoid propagating the exception, make sure we can handle the error later
$xmldata
=
false
;
}
if
(
empty
(
$xmldata
))
{
$error
=
error_get_last
();
Logger
::
info
(
'Unable to fetch metadata for "'
.
$entityId
.
'" from '
.
$mdq_url
.
': '
.
(
is_array
(
$error
)
?
$error
[
'message'
]
:
'no error available'
));
Logger
::
info
(
sprintf
(
'Unable to fetch metadata for "%s" from %s: %s'
,
$entityId
,
$mdq_url
,
(
is_array
(
$error
)
?
$error
[
'message'
]
:
'no error available'
)
));
return
null
;
}
/** @var string $xmldata */
$entity
=
SAMLParser
::
parseString
(
$xmldata
);
Logger
::
debug
(
__CLASS__
.
'
: completed parsing of [
'
.
$mdq_url
.
']'
);
Logger
::
debug
(
sprintf
(
'%s
: completed parsing of [
%s]'
,
__CLASS__
,
$mdq_url
)
);
$data
=
self
::
getParsedSet
(
$entity
,
$set
);
if
(
$data
===
null
)
{
throw
new
\
Exception
(
__CLASS__
.
'
: no metadata for set "
'
.
$set
.
'
" available from "
'
.
$entityId
.
'".'
throw
new
Exception
(
sprintf
(
'%s
: no metadata for set "
%s
" available from "
%s".'
,
__CLASS__
,
$set
,
$entityId
)
);
}
try
{
$this
->
writeToCache
(
$set
,
$entityId
,
$data
);
}
catch
(
\
Exception
$e
)
{
}
catch
(
Exception
$e
)
{
// Proceed without writing to cache
Logger
::
error
(
'Error writing MDQ result to cache:
'
.
$e
->
getMessage
());
Logger
::
error
(
sprintf
(
'Error writing MDQ result to cache:
%s'
,
$e
->
getMessage
())
)
;
}
return
$data
;
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment