Skip to content

Commit

Permalink
Merge branch 'release/20.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
cslzchen committed Nov 5, 2020
2 parents 353795b + 448229a commit 21a847d
Show file tree
Hide file tree
Showing 65 changed files with 2,952 additions and 646 deletions.
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,32 @@

We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO.

20.1.0 (11-05-2020)
===================

OSF CAS second release with FE re-design, BE improvements and DevOps updates

* FE
* Refactored styles to be consistent with both OSF and oldCAS
* Rewrote how authentication delegation info is retrieved and used
* Improved the behavior of inline error messages in login forms
* Added new / Rewrote existing authentication exception pages
* Improved UI / UX in responsive mode and on various screen dimensions

* BE
* Implemented a dedicated OSF CAS login context and a couple of pre-login
check actions to support ORCiD login and institution SSO
* Implemented ORCiD sign-up auto-redirect for OSF

* DevOps
* Updated tomcat server to work with its enclosing Shibboleth server
* Separated staging / production and local configurations
* Rewrote cas.properties into a helm charts template
* Improved build / run / reload for local development

* Other
* Replaced Apereo branding with COS / OSF in multiple places

20.0.0 (09-02-2020)
===================

Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ RUN cd cas-overlay \

FROM adoptopenjdk/openjdk11:alpine-jre AS cas

LABEL "Organization"="Apereo"
LABEL "Description"="Apereo CAS"
LABEL "Organization"="Center for Open Science"
LABEL "Description"="OSF CAS"

RUN cd / \
&& mkdir -p /etc/cas/config \
Expand All @@ -32,7 +32,7 @@ COPY etc/cas/services/ /etc/cas/services/
COPY etc/cas/saml/ /etc/cas/saml/
COPY --from=overlay cas-overlay/build/libs/cas.war cas-overlay/

EXPOSE 8080 8443
EXPOSE 8080

ENV PATH $PATH:$JAVA_HOME/bin:.

Expand Down
56 changes: 56 additions & 0 deletions Dockerfile-local
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
FROM adoptopenjdk/openjdk11:alpine-slim AS overlay

RUN mkdir -p cas-overlay
COPY ./src cas-overlay/src/
COPY ./gradle/ cas-overlay/gradle/
COPY ./gradlew ./settings.gradle ./build.gradle ./gradle.properties /cas-overlay/

RUN mkdir -p ~/.gradle \
&& echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties \
&& echo "org.gradle.configureondemand=true" >> ~/.gradle/gradle.properties \
&& cd cas-overlay \
&& chmod 750 ./gradlew \
&& ./gradlew --version;

RUN cd cas-overlay && ./gradlew clean build --parallel --no-daemon;
# The build process above in docker may takes a long time depending on your local resources. This OK if you only use
# CAS by building it once. For local development, building in local shell or with your IDE such as IntelliJ is much
# faster. Afterwards, simply comment out the above "RUN" command and enable the following "COPY" one. In fact, this
# stage can be skipped if you have the WAR built locally. Just need run the second stage with a modified WAR source.
# COPY ./build cas-overlay/build/

FROM adoptopenjdk/openjdk11:alpine-jre AS cas

LABEL "Organization"="Center for Open Science"
LABEL "Description"="OSF CAS"

RUN cd / \
&& mkdir -p /etc/cas/config \
&& mkdir -p /etc/cas/services \
&& mkdir -p /etc/cas/saml \
&& mkdir -p cas-overlay;

COPY etc/cas/ /etc/cas/

COPY etc/cas/config/ /etc/cas/config/
# Use "cas-local.properties" and "log4j2-local.xml" for local development
RUN rm etc/cas/config/cas.properties
COPY etc/cas/config/local/cas-local.properties etc/cas/config/cas.properties
COPY etc/cas/config/local/log4j2-local.xml etc/cas/config/log4j2.xml
RUN rm -r etc/cas/config/local

COPY etc/cas/services/ /etc/cas/services/
# Use registered services defined in "local/services" for local development
COPY etc/cas/services/local/* /etc/cas/services/
RUN rm -r etc/cas/services/local/

COPY etc/cas/saml/ /etc/cas/saml/

COPY --from=overlay cas-overlay/build/libs/cas.war cas-overlay/

EXPOSE 8080

ENV PATH $PATH:$JAVA_HOME/bin:.

WORKDIR cas-overlay
ENTRYPOINT ["java", "-server", "-noverify", "-Xmx2048M", "-jar", "cas.war"]
90 changes: 72 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ OSF CAS is the centralized authentication and authorization service for the [OSF
* OSF username and password login
* OSF username and verification key login
* OSF two-factor authentication
* **WIP** - Delegated authentication
* Delegated authentication
* ORCiD login
* **WIP** - CAS client: supports CAS protocol based institution SSO
* **WIP** - SAML service provider: supports SAML protocol based institution SSO
* **TBI** - OAuth authorization server for OSF
* **TBI** - SAML service provider

# Implementations

Expand All @@ -37,32 +39,84 @@ A legacy version can be found at [CAS Overlay](https://github.com/CenterForOpenS
- PostgreSQL `9.6`
- JDK `11`

# Build and Run OSF CAS
# Configure, Build and Run OSF CAS

It is recommended to use the provided scripts to [build](https://github.com/CenterForOpenScience/osf-cas/blob/develop/docker-build.sh) and [run](https://github.com/CenterForOpenScience/osf-cas/blob/develop/docker-run.sh) CAS. Refer to Apereo's [README.md](https://github.com/apereo/cas-overlay-template/tree/6.2#cas-overlay-template-) for more options.

Use [`cas.properties`](https://github.com/CenterForOpenScience/osf-cas/blob/develop/etc/cas/config/cas.properties) and [`Dockerfile`](https://github.com/CenterForOpenScience/osf-cas/blob/develop/Dockerfile) to configure staging and production servers. Use [`cas-local.properties`](https://github.com/CenterForOpenScience/osf-cas/blob/develop/etc/cas/config/local/cas-local.properties) and [`Dockerfile-local`](https://github.com/CenterForOpenScience/osf-cas/blob/develop/Dockerfile-local) for local development. To accelerate developing OSF CAS, use the [reload](https://github.com/CenterForOpenScience/osf-cas/blob/develop/docker-reload.sh) script to rebuild, reconfigure and restart the running container.

## OSF

OSF CAS requires a working OSF running locally. Refer to OSF's [README-docker-compose.md](https://github.com/CenterForOpenScience/osf.io/blob/develop/README-docker-compose.md) for how to set up and run OSF with `docker-compose`. Must disable `fakeCAS` to free port `8080`.

In `cas.propeties`, global JDBC settings can be found [here](https://github.com/cslzchen/osf-cas/blob/21bb277cc38b3364fd67a632c0bc7b7a6ffc9efd/etc/cas/config/cas.properties#L69-L73) and JPA specific settings can be found [here](https://github.com/cslzchen/osf-cas/blob/21bb277cc38b3364fd67a632c0bc7b7a6ffc9efd/etc/cas/config/cas.properties#L54-L60).
### OSF DB

More specifically, CAS requires a running OSF PostgreSQL database to handle authentication for OSF. Use the authentication handler's [JPA settings](https://github.com/CenterForOpenScience/osf-cas/blob/790cac1ac5a19754c67d6ea1f53afc26e1809d23/etc/cas/config/cas.properties#L70-L86) for [`OsfPostgresAuthenticationHandler`](https://github.com/CenterForOpenScience/osf-cas/blob/develop/src/main/java/io/cos/cas/osf/authentication/handler/support/OsfPostgresAuthenticationHandler.java) to connect to and access OSF DB.

Here is an example for local development. Use `192.168.168.167` to access host outside the docker container. Set `readOnly=true` since CAS only needs read-only access ([Principle of Least Privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)).

```yaml
# In `cas.properties` or `cas-local.properties`

cas.authn.osf-postgres.jpa.user=postgres
cas.authn.osf-postgres.jpa.password=
cas.authn.osf-postgres.jpa.driver-class=org.postgresql.Driver
cas.authn.osf-postgres.jpa.url=jdbc:postgresql://192.168.168.167:5432/osf?targetServerType=master&readOnly=true
cas.authn.osf-postgres.jpa.dialect=io.cos.cas.osf.hibernate.dialect.OsfPostgresDialect
```

## CAS DB

OSF CAS is configured to use the [JPA Ticket Registry](https://apereo.github.io/cas/6.2.x/ticketing/Configuring-Ticketing-Components.html#ticket-registry) for durable ticket storage. Thus, a relational database is required. Set up a `[email protected]` server and update *JPA Ticket Registry* [settings](https://github.com/cslzchen/osf-cas/blob/21bb277cc38b3364fd67a632c0bc7b7a6ffc9efd/etc/cas/config/cas.properties#L65-L113) in `cas.propeties` accordingly. Must use a port other than the already occupied `5432`.
The implementation of OSF CAS uses the [JPA Ticket Registry](https://apereo.github.io/cas/6.2.x/ticketing/Configuring-Ticketing-Components.html#ticket-registry) for durable ticket storage and thus requires a relational database. Set up a `[email protected]` server and review [JPA Ticket Registry settings](https://github.com/CenterForOpenScience/osf-cas/blob/790cac1ac5a19754c67d6ea1f53afc26e1809d23/etc/cas/config/cas.properties#L90-L138). In most cases, only [Database connections](https://github.com/CenterForOpenScience/osf-cas/blob/790cac1ac5a19754c67d6ea1f53afc26e1809d23/etc/cas/config/cas.properties#L104-L108) need to be updated. In addition, [JDBC settings](https://github.com/CenterForOpenScience/osf-cas/blob/790cac1ac5a19754c67d6ea1f53afc26e1809d23/etc/cas/config/cas.properties#L96-L98) can be adjusted if necessary.

Here is an example for local development. Use `192.168.168.167` to access host outside the docker container. Use the port `54321` since the default `5432` one has been used by OSF DB. Update `pg_hba.conf` to grant proper access permission depending on the setup.

```yaml
# In `cas.properties` or `cas-local.properties`

cas.ticket.registry.jpa.user=longzechen
cas.ticket.registry.jpa.password=
cas.ticket.registry.jpa.driver-class=org.postgresql.Driver
cas.ticket.registry.jpa.url=jdbc:postgresql://192.168.168.167:54321/osf-cas?targetServerType=master
cas.ticket.registry.jpa.dialect=org.hibernate.dialect.PostgreSQL95Dialect
```

```yaml
# In `pg_hba.conf`

# TYPE DATABASE USER ADDRESS METHOD
host osf-cas longzechen 192.168.168.167/24 trust
```

## Signing and Encryption Keys

Refer to [settings](https://github.com/cslzchen/osf-cas/blob/21bb277cc38b3364fd67a632c0bc7b7a6ffc9efd/etc/cas/config/cas.properties#L117-L133) in `cas.properties` for signing and encrypting client session and ticket granting cookie.
Refer to [signing and encryption settings](https://github.com/CenterForOpenScience/osf-cas/blob/790cac1ac5a19754c67d6ea1f53afc26e1809d23/etc/cas/config/cas.properties#L142-L158) in `cas.properties` for signing and encrypting client sessions and ticket granting cookies. Use the following default keys **for local development only**.

```yaml
# In `cas-local.properties`

cas.webflow.crypto.signing.key=7okipSDHBKuZL2n66cfYU4OH1Z_BRYkmEJazc29hzhXCXbRvws7Hv4_hEVd4E2osMrgIEdykzV2hAVD9CCQpJw
cas.webflow.crypto.encryption.key=1A9hLtxA-Es-hbQsfxqxxw

cas.tgc.crypto.signing.key=_WTRQmXGuq-mx2pTjNCXuX5971-e8KOCFOa27Mh5I3oBobYSzyUrLS9rfSiXQQDolJrJrWv7jURID1vtouznHg
cas.tgc.crypto.encryption.key=dcjD5PIfrcqGM8tv4_FGubcay-DbqKPPoz9xQ3IHQi0
```

## Authentication Delegation

### ORCiD Login

Set up a developer app at [ORCiD](https://orcid.org/developer-tools) with `http://localhost:8080/login` and `http://192.168.168.167:8080/login` as *redirect URIs*. Update
`cas.authn.pac4j.orcid.id` and `cas.authn.pac4j.orcid.secret` in `cas.properties` [settings](https://github.com/cslzchen/osf-cas/blob/21bb277cc38b3364fd67a632c0bc7b7a6ffc9efd/etc/cas/config/cas.properties#L186-L192).
To enable ORCiD login, update `cas.authn.pac4j.orcid.id` and `cas.authn.pac4j.orcid.secret` [here](https://github.com/CenterForOpenScience/osf-cas/blob/790cac1ac5a19754c67d6ea1f53afc26e1809d23/etc/cas/config/cas.properties#L212-L213) in delegation settings accordingly.

For local development, set up a developer app at [ORCiD](https://orcid.org/developer-tools) with `http://localhost:8080/login` and `http://192.168.168.167:8080/login` as *redirect URIs*.

### Institution Login

### `fakeCAS` Login
( ... WIP ... )

With OSF CAS running locally as the authentication server for OSF, `fakeCAS` can be configured to serve as an identity provider. Simply update `fakecas` in OSF's [docker-compose.yaml](https://github.com/CenterForOpenScience/osf.io/blob/dc87c86b2afb7ad4e801b23c6428e3d2169e3e36/docker-compose.yml#L235-L247) to listen on port 8081.
#### `fakeCAS` Login (Local Development Only)

With OSF CAS running locally as the authentication server for OSF, the previously disabled `fakeCAS` can be re-configured to serve as an identity provider. Simply update `fakecas` in OSF's [docker-compose.yaml](https://github.com/CenterForOpenScience/osf.io/blob/dc87c86b2afb7ad4e801b23c6428e3d2169e3e36/docker-compose.yml#L235-L247) to listen on port `8081`.

```
fakecas:
Expand All @@ -76,15 +130,15 @@ fakecas:
stdin_open: true
```

Related settings in `cas.propeties` can be found [here](https://github.com/cslzchen/osf-cas/blob/21bb277cc38b3364fd67a632c0bc7b7a6ffc9efd/etc/cas/config/cas.properties#L196-L199).
Related `cas.propeties` settings can be found [here](https://github.com/CenterForOpenScience/osf-cas/blob/790cac1ac5a19754c67d6ea1f53afc26e1809d23/etc/cas/config/local/cas-local.properties#L192-L235).

## Build and Run
```yaml
# In `cas-local.properties`

It is recommended to use the `Dockerfile` and the provided scripts to build and run CAS.
cas.authn.osf-postgres.institution-clients[2]=${cas.authn.pac4j.cas[2].client-name}

```bash
./docker-build.sh
./docker-run.sh
cas.authn.pac4j.cas[2].login-url=http://192.168.168.167:8081/login
cas.authn.pac4j.cas[2].client-name=fakecas
cas.authn.pac4j.cas[2].protocol=CAS30
cas.authn.pac4j.cas[2].callback-url-type=QUERY_PARAMETER
```

Refer to Apereo's [README.md](https://github.com/apereo/cas-overlay-template/tree/6.2#cas-overlay-template-) for more options.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ dependencies {
// JPA Ticket Registry
implementation "org.apereo.cas:cas-server-support-jpa-ticket-registry:${project.'cas.version'}"

// Tomcat Catalina
implementation "org.apache.tomcat:tomcat-catalina:${springBootTomcatVersion}"

// Hibernate
implementation "org.hibernate:hibernate-core:${hibernateCoreVersion}"

Expand Down
18 changes: 18 additions & 0 deletions docker-reload.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

# Rebuild locally and replace the WAR
./gradlew clean build
docker cp ./build/libs/cas.war cas:/cas-overlay

# Sync configuration files
docker exec -d cas sh -c "rm -rf /etc/cas/config/*"
docker cp ./etc/cas/config/local/cas-local.properties cas:/etc/cas/config/cas.properties
docker cp ./etc/cas/config/local/log4j2-local.xml cas:/etc/cas/config/log4j2.xml

# Sync JSON registered service files
docker exec -d cas sh -c "rm -rf /etc/cas/services/*"
docker cp ./etc/cas/services/local/. cas:/etc/cas/services

# Restart the container
docker restart cas
docker logs -f --tail 0 cas
4 changes: 2 additions & 2 deletions docker-run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
docker stop cas > /dev/null 2>&1
docker rm cas > /dev/null 2>&1
image_tag=(`cat gradle.properties | grep "cas.version" | cut -d= -f2`)
docker run -d -p 8080:8080 -p 8443:8443 --name="cas" apereo/cas:"v${image_tag}"
docker logs -f cas
docker run -d -p 8080:8080 --name="cas" apereo/cas:"v${image_tag}"
docker logs -f cas
Loading

0 comments on commit 21a847d

Please sign in to comment.