CSW Schnittstelle¶
Allgemeines¶
Offizielle Dokumentation
Weiterführende Informationen zu Installation und Konfiguration finden sich in der offiziellen pycsw-Dokumentation.
Die CSW-Schnittstelle stellt Metadaten im InGrid-System über den OGC CSW 2.0.2 AP ISO 1.0-Standard bereit und eignet sich als eigenständiger Metadatenkatalog innerhalb einer InGrid-Infrastruktur. Umgesetzt wird sie mit pycsw, einem quelloffenen CSW-Server auf Python-Basis.
In der InGrid-Umgebung dient pycsw als zentrales Katalog-Ziel für einliefernde Komponenten (Editor, Harvester) und stellt Metadaten via CSW-Schnittstelle für abfragende Komponenten wie das Portal bereit.
Systemvoraussetzungen¶
| Systembestandteil | Anforderung | |
|---|---|---|
| Software | PostgreSQL | 15 oder höher (via Docker) |
Installation¶
Docker¶
-
Docker-Image
Das offizielle Docker-Image von pycsw:
Für den Betrieb wird eine PostgreSQL-Datenbank empfohlen.
services:
pycsw:
image: geopython/pycsw
restart: unless-stopped
environment:
- PYCSW_CONFIG=/etc/pycsw/pycsw.yml
volumes:
- ./pycsw/pycsw.yml:/etc/pycsw/pycsw.yml
ports:
- "8000:8000"
depends_on:
pycsw-db:
condition: service_healthy
networks:
- ingrid-network
pycsw-db:
image: postgres:15
restart: unless-stopped
environment:
- POSTGRES_DB=pycsw
- POSTGRES_USER=pycsw
- POSTGRES_PASSWORD=pycsw
volumes:
- pycsw-data:/var/lib/postgresql/data
networks:
- ingrid-network
volumes:
pycsw-data:
networks:
ingrid-network:
Konfiguration¶
pycsw wird über eine YAML-Konfigurationsdatei (pycsw.yml) konfiguriert. Eine vollständige Referenz aller Parameter ist in der offiziellen Konfigurationsdokumentation verfügbar.
Beispiel pycsw.yml
server:
url: http://<host>:8000
mimetype: application/xml; charset=UTF-8
encoding: UTF-8
language: de
maxrecords: 10
pretty_print: true
manager:
transactions: "true"
allowed_ips: 127.0.0.1,<IP-Adresse-Editor>,<IP-Adresse-Harvester>
metadata:
identification:
title: Mein Metadatenkatalog
description: OGC CSW-Katalog auf Basis von pycsw
keywords:
- pycsw
- Metadaten
- CSW
keywords_type: theme
fees: None
accessconstraints: None
provider:
name: Meine Organisation
url: https://www.meine-organisation.de
contact:
name: Kontaktname
position: Datenmanagement
email: kontakt@meine-organisation.de
role: pointOfContact
repository:
database: postgresql://pycsw:pycsw@pycsw-db/pycsw
table: records
Die wichtigsten Einstellungen im Überblick:
| Einstellung | Beschreibung | Dokumentation |
|---|---|---|
server.url | Öffentliche URL des CSW-Endpunkts | server |
server.maxrecords | Maximale Anzahl zurückgegebener Datensätze pro Anfrage | server |
manager.transactions | CSW-T aktivieren (true/false) | manager |
manager.allowed_ips | IP-Adressen mit Schreibzugriff (CSW-T) | manager |
repository.database | Datenbankverbindung (PostgreSQL oder SQLite) | repository |
repository.table | Tabellenname im Datenbankschema | repository |
CSW-T Sicherheit
CSW-T ermöglicht das Schreiben, Aktualisieren und Löschen von Metadatensätzen. Stellen Sie sicher, dass unter manager.allowed_ips ausschließlich autorisierte IP-Adressen eingetragen sind.
Authentifizierung¶
pycsw bietet keine eingebaute Benutzerauthentifizierung. Die Absicherung erfolgt auf zwei Ebenen:
- CSW-T (Schreibzugriff): Über
manager.allowed_ipswerden nur explizit erlaubte IP-Adressen zum Schreiben zugelassen. - CSW (Lesezugriff): Für einen komplett nicht-öffentlichen Katalog empfiehlt sich ein vorgeschalteter Reverse Proxy mit HTTP Basic Auth.
Info
Basic Auth schützt alle Anfragen – GET und POST gleichermaßen. Eine Einschränkung auf nur schreibende Methoden ist nicht möglich, da CSW-Lese- und Schreiboperationen beide per POST übertragen werden und sich auf HTTP-Ebene nicht unterscheiden lassen.
Reverse Proxy mit HTTP Basic Auth (Apache)¶
Eine Passwortdatei kann mit htpasswd erstellt werden:
Beispielkonfiguration für Apache:
<VirtualHost *:80>
ServerName <pycsw-host>
ProxyPass / http://pycsw:8000/
ProxyPassReverse / http://pycsw:8000/
<Location />
AuthType Basic
AuthName "CSW Katalog"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Location>
</VirtualHost>
Erforderliche Apache-Module:
Info
Einliefernde Komponenten (Editor, Harvester) müssen bei aktivierter Basic Auth die Credentials in ihrer Verbindungskonfiguration hinterlegen.
Response Transformation¶
TODO
InGrid Editor¶
Der InGrid Editor kann Metadatensätze via CSW-T direkt in pycsw einliefern. Damit der Editor gegen pycsw publizieren kann, müssen folgende Voraussetzungen erfüllt sein:
- In pycsw ist die CSW-T-Transaktion aktiviert (
manager.transactions: "true") - Die IP-Adresse des Editors ist unter
manager.allowed_ipseingetragen - Im Editor ist die Export-Konfiguration auf den pycsw-Endpunkt gesetzt
Der CSW-T-Endpunkt von pycsw ist erreichbar unter:
Ein Beispiel-Request für das Einfügen eines Datensatzes:
curl --location 'http://<pycsw-host>' \
--header 'Content-Type: application/xml' \
--data-raw '<?xml version="1.0" encoding="UTF-8"?>
<csw:Transaction service="CSW" version="2.0.2"
xmlns:csw="http://www.opengis.net/cat/csw/2.0.2"
xmlns:gmd="http://www.isotc211.org/2005/gmd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-publication.xsd">
<csw:Insert>
<!-- vollständiges ISO 19139 Metadatendokument -->
</csw:Insert>
</csw:Transaction>'
InGrid Harvester¶
Der InGrid Harvester kann pycsw als CSW-Katalogziel verwenden. Dabei werden geerntete Metadaten per CSW-T an pycsw übertragen.
Einrichtung in der Harvester-Konfiguration:
- In der Harvester-Oberfläche eine neue Katalog-Verbindung vom Typ CSW anlegen
- Als Endpunkt den pycsw-Endpunkt eintragen:
http://<pycsw-host>:<port> - Sicherstellen, dass die IP-Adresse des Harvesters in
manager.allowed_ipsvon pycsw eingetragen ist
Info
Weitere Informationen zur Einrichtung von Katalogzielen finden sich im Leitfaden Harvester-Katalog.
InGrid Portal¶
Das InGrid Portal kann Metadaten über die CSW-Schnittstelle von pycsw abfragen und zur Darstellung aufbereiten.
Die CSW-Abfrage-URL lautet:
Diese URL wird in der Portal-Konfiguration als CSW-Endpunkt hinterlegt. Über die Umgebungsvariable INGRID_API verweist das Portal auf die InGrid API, die als Vermittler zwischen Portal und den angebundenen Datenquellen agiert.
Eine vollständige Übersicht aller Portal-Konfigurationsoptionen ist in der Portal-Dokumentation beschrieben.
FAQ¶
Ausgabeformat
Alle GetRecords- und GetRecordById-Beispiele verwenden ISO 19139 (http://www.isotc211.org/2005/gmd) als outputSchema. Dieses Format wird für den Austausch von Geodaten-Metadaten im InGrid-Kontext vorausgesetzt.
Grundlegende Abfragen¶
GetCapabilities: Wie kann die CSW-Schnittstelle getestet werden?
Der einfachste Smoke-Test ist ein GetCapabilities-Request. Er gibt die Fähigkeiten des Servers zurück und zeigt an, ob pycsw erreichbar ist.
Zum Testen eignen sich Tools wie Postman oder vergleichbare REST-Clients. Bei POST-Anfragen muss der Content-Type application/xml gesetzt werden.
GET
POST XML
GetRecords: Wie werden alle Datensätze paginiert abgerufen?
Mit startPosition wird der Cursor verschoben, mit maxRecords die Seitengröße festgelegt. Der Antwortparameter numberOfRecordsMatched liefert die Gesamttrefferanzahl und dient als Abbruchbedingung.
GET
http://<pycsw-host>/csw?service=CSW&version=2.0.2&request=GetRecords&elementSetName=full&resultType=results&outputSchema=http://www.isotc211.org/2005/gmd&startPosition=1&maxRecords=10&typeNames=csw:Record
POST XML
<?xml version="1.0" encoding="UTF-8"?>
<csw:GetRecords xmlns:csw="http://www.opengis.net/cat/csw/2.0.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2"
service="CSW" version="2.0.2"
resultType="results"
outputFormat="application/xml"
outputSchema="http://www.isotc211.org/2005/gmd"
startPosition="1" maxRecords="10">
<csw:Query typeNames="csw:Record">
<csw:ElementSetName>full</csw:ElementSetName>
</csw:Query>
</csw:GetRecords>
GetRecordById: Wie wird ein einzelner Datensatz per ID abgerufen?
GET
http://<pycsw-host>/csw?service=CSW&version=2.0.2&request=GetRecordById&outputSchema=http://www.isotc211.org/2005/gmd&elementSetName=full&id=<UUID>
POST XML
Filterabfragen¶
GetRecords: Wie wird nach Partner gefiltert?
InGrid-spezifisch
Die Filterung nach Partner und Anbieter basiert auf einer InGrid-Konvention: Einliefernde Komponenten (Editor, Harvester) schreiben die Zugehörigkeit als strukturiertes Schlagwort in das Feld apiso:Subject. Diese Keywords sind kein Bestandteil des CSW- oder ISO-Standards.
In InGrid werden Partner als Schlagwort im Feld apiso:Subject mit dem Präfix organisation: gespeichert. Da das Feld die gesamte kommagetrennte Schlagwortliste enthält, muss PropertyIsLike für die Teilsuche verwendet werden – PropertyIsEqualTo würde den vollständigen Spalteninhalt auf exakte Übereinstimmung prüfen und damit keine Treffer liefern.
GET (CQL_TEXT)
http://<pycsw-host>/csw?service=CSW&version=2.0.2&request=GetRecords&elementSetName=full&resultType=results&outputSchema=http://www.isotc211.org/2005/gmd&startPosition=1&maxRecords=100&typeNames=csw:Record&constraint=apiso:Subject like '%organisation:bund%'&constraintLanguage=CQL_TEXT
POST XML (OGC Filter)
<csw:GetRecords xmlns:csw="http://www.opengis.net/cat/csw/2.0.2"
xmlns:ogc="http://www.opengis.net/ogc"
service="CSW" version="2.0.2"
resultType="results"
outputSchema="http://www.isotc211.org/2005/gmd">
<csw:Query typeNames="csw:Record">
<csw:ElementSetName>full</csw:ElementSetName>
<csw:Constraint version="1.1.0">
<ogc:Filter>
<ogc:PropertyIsLike wildCard="%" singleChar="_" escapeChar="\">
<ogc:PropertyName>apiso:Subject</ogc:PropertyName>
<ogc:Literal>%organisation:bund%</ogc:Literal>
</ogc:PropertyIsLike>
</ogc:Filter>
</csw:Constraint>
</csw:Query>
</csw:GetRecords>
GetRecords: Wie wird nach Anbieter gefiltert?
Anbieter werden mit dem Präfix sub_organisation: als Schlagwort abgelegt. Das Abfragemuster ist identisch mit der Partnerabfrage:
GET (CQL_TEXT)
http://<pycsw-host>/csw?service=CSW&version=2.0.2&request=GetRecords&elementSetName=full&resultType=results&outputSchema=http://www.isotc211.org/2005/gmd&startPosition=1&maxRecords=100&typeNames=csw:Record&constraint=apiso:Subject like '%sub_organisation:ni%'&constraintLanguage=CQL_TEXT
POST XML (OGC Filter)
<csw:GetRecords xmlns:csw="http://www.opengis.net/cat/csw/2.0.2"
xmlns:ogc="http://www.opengis.net/ogc"
service="CSW" version="2.0.2"
resultType="results"
outputSchema="http://www.isotc211.org/2005/gmd">
<csw:Query typeNames="csw:Record">
<csw:ElementSetName>full</csw:ElementSetName>
<csw:Constraint version="1.1.0">
<ogc:Filter>
<ogc:PropertyIsLike wildCard="%" singleChar="_" escapeChar="\">
<ogc:PropertyName>apiso:Subject</ogc:PropertyName>
<ogc:Literal>%sub_organisation:ni%</ogc:Literal>
</ogc:PropertyIsLike>
</ogc:Filter>
</csw:Constraint>
</csw:Query>
</csw:GetRecords>
GetRecords: Wie wird nach ResourceIdentifier gefiltert?
Um Datensätze einer bestimmten Datenquelle über ihren eindeutigen Ressourcenbezeichner abzufragen:
GET (CQL_TEXT)
http://<pycsw-host>/csw?service=CSW&version=2.0.2&request=GetRecords&elementSetName=full&resultType=results&outputSchema=http://www.isotc211.org/2005/gmd&startPosition=1&maxRecords=10&typeNames=csw:Record&constraint=apiso:ResourceIdentifier='7988c147-7523-45bb-8f18-7f39d0d20541'&constraintLanguage=CQL_TEXT
POST XML (OGC Filter)
<csw:GetRecords xmlns:csw="http://www.opengis.net/cat/csw/2.0.2"
xmlns:ogc="http://www.opengis.net/ogc"
service="CSW" version="2.0.2"
resultType="results"
outputSchema="http://www.isotc211.org/2005/gmd"
startPosition="1" maxRecords="10">
<csw:Query typeNames="csw:Record">
<csw:ElementSetName>full</csw:ElementSetName>
<csw:Constraint version="1.1.0">
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>apiso:ResourceIdentifier</ogc:PropertyName>
<ogc:Literal>7988c147-7523-45bb-8f18-7f39d0d20541</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
</csw:Constraint>
</csw:Query>
</csw:GetRecords>