Skip to content

Commit

Permalink
Fix user being logged out after streaming video
Browse files Browse the repository at this point in the history
The service call that streamed video was never returning, and that would
cause an internal error in the web server that would invalidate the user's
session and force them to log in again.

This also adds support for configuring the LDAP server through environment
variables that can be set on the Docker container.

Signed-off-by: P. J. Reed <[email protected]>
  • Loading branch information
pjreed committed May 11, 2020
1 parent 0d38369 commit 2c00f94
Show file tree
Hide file tree
Showing 7 changed files with 303 additions and 55 deletions.
44 changes: 44 additions & 0 deletions OpenLDAP_data.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People

dn: ou=Groups,dc=example,dc=com
objectClass: organizationalUnit
ou: Groups

dn: cn=Artist,ou=Groups,dc=example,dc=com
objectClass: posixGroup
cn: SUBGROUP
gidNumber: 5000

dn: uid=ben,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: ben
sn: Affleck
givenName: Ben
cn: Ben Affleck
displayName: Ben
uidNumber: 10001
gidNumber: 5000
userPassword: benspassword
gecos: Ben Affleck
loginShell: /bin/bash
homeDirectory: USERDIRECTORY1

dn: uid=bob,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: bob
sn: Marley
givenName: Bob
cn: Bob Marley
displayName: Bob
uidNumber: 10002
gidNumber: 5000
userPassword: bobspassword
gecos: Bob Marley
loginShell: /bin/bash
homeDirectory: USERDIRECTORY2
114 changes: 99 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,14 @@ are stored and will be manually uploading files there.
- **Tagging**: Bags can be tagged and searched for with arbitrary metadata
strings. Existing tags on arbitrary metadata topics in bag files will be
automatically read.
- **Ldap Login**: Authenticating users via LDAP server, just provide the
correct server address in `SecurityConfig.java` file. Exclusive group access
can also be done by specifying the name of a specific group. If you are
looking for a simple LDAP just check the branch with openLDAP feature
and replace the address with your institute's LDAP address. In this scheme,
there are two types of users, one is authenticated from LDAP and another
one is admin. All users have to login first via LDAP login page except
admin, he can login directly by visiting the url `/signin`. Admin can also
login once logged in as LDAP user and then by accessing Admin login option
in the navigation menu, see images below for understanding. First one is
LDAP login page and second one is after LDAP login. There's only one logout
button in all scenarios which will end the session and bring you out to LDAP
login page again.

- **LDAP Login**: If enabled, the bag database will authenticate users against
an LDAP database before allowing access. LDAP configuration details can
be provided by customizing environment variables when starting it as a
Docker container.
The Admin user is still handled separately and can log in directly by
visiting the URL `/signin` or by loggin in as a normal user and then using
the Navigation menu.

![Sample Screenshot](doc/LDAP_login.png)
![Sample Screenshot](doc/LDAP_Admin_login.png)

Expand Down Expand Up @@ -103,6 +97,10 @@ if you do so it will have to rebuild the database every time it restarts. Inste
you should link it to an external database. PostgreSQL with PostGIS extensions is
the only supported database.

The instructions here will describe how to manually create Docker containers, but
you may find it easier to use [Docker Compose](https://docs.docker.com/compose/) to
run the included `docker-compose.yml` file instead; just customize it to your needs.

First, create a virtual network for the containers:
```bash
docker network create bagdb
Expand Down Expand Up @@ -230,6 +228,26 @@ Header header
```
If there are no topics configured or none of them are found, it will try to use the first topic it can find that publishes the `sensor_msgs/NavSatFix`, `gps_common/GPSFix`, or `marti_gps_common/GPSFix` messages, in that order.

##### LDAP_BINDDN

If authenticating against an LDAP server that requires authentication, the Bind DN. If this is left blank, it will not attempt to authenticate.

##### LDAP_BIND_PASSWORD

If authenticating against an LDAP server that requires authentication, the password for the Bind DN.

##### LDAP_SEARCH_BASE

The search base for finding users in the LDAP server.

##### LDAP_SERVER

The LDAP server for authentication. If set to an empty string, LDAP authentication will not be enabled, and anonymous users may connect.

##### LDAP_USER_PATTERN

The pattern for finding user DNs in the LDAP server. `{0}` will be replaced with the username from the login form.

##### DEBUG_JAVASCRIPT

Set this to `true` to force the application to load non-minified versions of Javascript files. This will increase load times. The default is `false`.
Expand Down Expand Up @@ -260,7 +278,73 @@ Only Tomcat 8.0 with Java 8.0 has been tested.
vehicleNameTopics:
- /vms/vehicle_name
```
5. Look inside the log file at `${TOMCAT_HOME}/logs/bag_database.log` to find the automatically-generated administrator password.
6. Log in through the GUI and use the Maintenance panel to change the password.
7. Note that in order for video streaming to work, `ffmpeg` version 3 or higher must be available on the system path.


#### Set up a Standalone LDAP Server

All these steps are inspired from this [blog](https://www.linux.com/topic/desktop/how-install-openldap-ubuntu-server-1804/).

1. Installation:
```
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install slapd ldap-utils -y
```

During the setup, it will ask you to provide an Administrator password.

2. Configuration:
```
sudo dpkg-reconfigure slapd
```

It will ask you several questions for configuring SLAPD; these example values have been tested.

- Omit: No (Keeps default configuration of the ldap server)
- DNS domain name: example.com
- Organisation name: Example Organization
- Admin password: pwd (Keep same as the earlier one and confirm the same)
- Database Type: MDB
- Purging Database: Yes
- Move old Database: Yes

3. There is an example file in this repository named `OpenLDAP_data.ldif` that will
create a few organizational units in your LDAP database and then add a few users.
You should customize this to suit your organization. The base structure of the
file is also adapted from the [blog](https://www.linux.com/topic/desktop/how-install-openldap-ubuntu-server-1804/).
```
ldapadd -x -D cn=admin,dc=example,dc=com -W -f OpenLDAP_data.ldif
```

You will be asked for the `admin` password here.

4. The OpenLDAP server should be running by now, you can check the status with the
following command:
```
sudo systemctl status slapd
```

If you need to manually restart or enable it use the following commands:
```
sudo systemctl enable slapd
sudo systemctl restart slapd
```

5. In case you need to remove OpenLDAP use the following commands taken from this [blog](https://installlion.com/ubuntu/xenial/main/s/slapd/uninstall/index.html):
```
sudo apt-get remove --auto-remove slapd
```

And to completely purge remove:
```
sudo apt-get purge --auto-remove slapd
```

6. Now you can launch the Bag Database. If you used the example LDIF file to load users,
you can log in with these credentials:
- username: ben, password: benspassword
- username: bob, password: bobspassword
32 changes: 29 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ services:
networks:
- bagdb
depends_on:
- bagdb-postgres
- postgres
- openldap
ports:
- "8080:8080"
volumes:
Expand All @@ -14,22 +15,47 @@ services:
ADMIN_PASSWORD: "letmein"
DB_DRIVER: org.postgresql.Driver
DB_PASS: letmein
DB_URL: "jdbc:postgresql://bagdb-postgres/bag_database"
DB_URL: "jdbc:postgresql://postgres/bag_database"
DB_USER: bag_database
USE_BING: "false"
USE_TILE_MAP: "true"
METADATA_TOPICS: "/metadata"
VEHICLE_NAME_TOPICS: "/vms/vehicle_name, /vehicle_name"
GPS_TOPICS: "/localization/gps, gps, /vehicle/gps/fix, /localization/sensors/gps/novatel/raw, /localization/sensors/gps/novatel/fix, /imu_3dm_node/gps/fix, /local_xy_origin"
bagdb-postgres:
LDAP_BINDDN: "cn=admin,dc=example,dc=com"
LDAP_BIND_PASSWORD: "P@ssw0rd"
LDAP_SEARCH_BASE: "ou=People,dc=example,dc=com"
LDAP_SERVER: 'ldap://openldap' # Replace this with an empty string to disable LDAP auth
LDAP_USER_PATTERN: "uid={0},ou=People,dc=example,dc=com"
postgres:
image: mdillon/postgis:latest
networks:
- bagdb
volumes:
- postgres:/var/lib/postgresql/data
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: letmein
POSTGRES_USER: bag_database
POSTGRES_DB: bag_database
openldap:
image: osixia/openldap:1.3.0
networks:
- bagdb
volumes:
- ldap:/var/lib/ldap
- slapd:/etc/ldap/slapd.d
ports:
- "389:389"
- "636:636"
environment:
LDAP_ORGANIZATION: "Example Organization"
LDAP_DOMAIN: "example.com"
LDAP_ADMIN_PASSWORD: "P@ssw0rd"
networks:
bagdb: {}
volumes:
postgres:
ldap:
slapd:
10 changes: 10 additions & 0 deletions src/main/docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ TILE_MAP_URL=${TILE_MAP_URL-"http://{a-d}.tile.stamen.com/terrain/{z}/{x}/{y}.jp
TILE_WIDTH_PX=${TILE_WIDTH_PX-256}
TILE_HEIGHT_PX=${TILE_HEIGHT_PX-256}
FASTER_CODEC=${FASTER_CODEC:-false}
LDAP_BINDDN=${LDAP_BINDDN:-}
LDAP_BIND_PASSWORD=${LDAP_BIND_PASSWORD:-}
LDAP_SEARCH_BASE=${LDAP_SEARCH_BASE:-}
LDAP_SERVER=${LDAP_SERVER:-}
LDAP_USER_PATTERN=${LDAP_USER_PATTERN:-}

if [ ! -f ${HOME}/.ros-bag-database/settings.yml ]
then
Expand All @@ -40,6 +45,11 @@ metadataTopics: ${METADATA_TOPICS}
gpsTopics: ${GPS_TOPICS}
debugJavascript: ${DEBUG_JAVASCRIPT}
fasterCodec: ${FASTER_CODEC}
ldapBindDn: ${LDAP_BINDDN}
ldapBindPassword: ${LDAP_BIND_PASSWORD}
ldapSearchBase: ${LDAP_SEARCH_BASE}
ldapServer: ${LDAP_SERVER}
ldapUserPattern: ${LDAP_USER_PATTERN}
" > ${HOME}/.ros-bag-database/settings.yml
fi

Expand Down
24 changes: 18 additions & 6 deletions src/main/java/com/github/swrirobotics/bags/BagController.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
Expand Down Expand Up @@ -127,22 +130,31 @@ public ModelAndView getImage(@RequestParam Long bagId,
}

@RequestMapping("/video")
public void getVideo(@RequestParam Long bagId,
@RequestParam String topic,
@RequestParam Long frameSkip,
HttpServletResponse response) {
public ResponseEntity<StreamingResponseBody> getVideo(@RequestParam Long bagId,
@RequestParam String topic,
@RequestParam Long frameSkip,
HttpServletResponse response) {
myLogger.info("getVideo: " + bagId + ":" + topic);
try {
OutputStream output = response.getOutputStream();
response.setContentType("video/webm;codecs=\"vp8\"");
myBagService.writeVideoStream(bagId, topic, frameSkip, output);
StreamingResponseBody stream = out -> {
try {
myBagService.writeVideoStream(bagId, topic, frameSkip, output);
}
catch (BagReaderException e) {
myLogger.error("Error reading bag file:", e);
}
};
return new ResponseEntity<>(stream, HttpStatus.OK);
}
catch (BagReaderException | IOException e) {
catch (IOException e) {
myLogger.error("Error getting video stream:", e);
}
finally {
myLogger.info("Finished getVideo()");
}
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}

@RequestMapping("/update")
Expand Down
Loading

0 comments on commit 2c00f94

Please sign in to comment.