Commit 1ca0422f authored by Petter Goksøyr Åsen's avatar Petter Goksøyr Åsen
Browse files

Initial commit

parents
VIRTUOSO_IMAGE_TAG=76da0400a766927567d3c4b3229ce6d02e567c2f
ELASTICSEARCH_IMAGE_TAG=9be13a2a600e3112430c2a54a4493373e73a94b3
KOHA_IMAGE_TAG=18b0e900f138f07f36f8c518bc7c260df89fa293
*.ttl.gz
\ No newline at end of file
all:
docker-compose up -d
build: NOCACHE =
rebuild: NOCACHE = --no-cache
build rebuild:
ifndef CONTAINER
@echo "INFO: CONTAINER variable not set, handling all containers"
endif
docker-compose build $(NOCACHE) $(CONTAINER)
docker-compose up -d $(CONTAINER)
dev:
ifndef CONTAINER
@echo "ERROR: missing required CONTAINER variable, ex: make dev CONTAINER=timber"
@exit 1
endif
-docker-compose stop $(CONTAINER)
-docker-compose rm -f $(CONTAINER)
docker-compose -f docker-compose.yml -f docker-compose-dev.yml build $(CONTAINER)
docker-compose -f docker-compose.yml -f docker-compose-dev.yml up $(CONTAINER)
KATALOG_GRAPH=https://katalog.deichman.no
define clear_graph
docker exec -i virtuoso bash -c "cd /data && echo -e \"log_enable(3,1);\nSPARQL DROP SILENT GRAPH <$(1)>;\ncheckpoint;\" | isql-v -P \$$DBA_PASSWORD"
endef
define import_graph
docker exec -i virtuoso bash -c "cd /data && echo -e \"log_enable (2);\nDELETE FROM DB.DBA.load_list;\nld_dir('/data', '$(1)', '$(2)');\nrdf_loader_run();\ncheckpoint;\" | isql-v -P \$$DBA_PASSWORD"
endef
virtuoso_clean:
$(call clear_graph,http://localuriqaserver/sparql)
$(call clear_graph,http://www.openlinksw.com/schemas/virtrdf#)
$(call clear_graph,http://www.w3.org/ns/ldp#)
$(call clear_graph,http://localhost:8890/sparql)
$(call clear_graph,http://localhost:8890/DAV/)
$(call clear_graph,http://www.w3.org/2002/07/owl#)
$(call clear_graph,$(KATALOG_GRAPH))
virtuoso_import_katalog: virtuoso_clean
wget -N http://static.deichman.no/katalog_000001.ttl.gz
docker cp katalog_000001.ttl.gz virtuoso:/data/katalog.ttl.gz
$(call import_graph,katalog.ttl.gz,$(KATALOG_GRAPH))
IMAGES=timber katalog services tjenestekatalog euler sibyl authorization-server mimir
TODAY=$(shell date +%F)
push: build
ifndef TAG
@echo "ERROR: missing required TAG variable, ex: make push TAG=b1"
@exit 1
endif
#docker login --username=$DOCKERHUB_USERNAME --password=$DOCKERHUB_PASSWORD
for image in $(IMAGES) ; do \
docker tag deichman_$$image digibib/$$image:$(TODAY).$$TAG ; \
docker tag deichman_$$image digibib/$$image:latest ; \
docker push digibib/$$image:$(TODAY).$$TAG ; \
docker push digibib/$$image:latest ; \
done
deploy:
ifndef TAG
@echo "ERROR: missing required TAG variable, ex: make deploy TARGET=test-1 TAG=b1"
@exit 1
endif
ifndef TARGET
@echo "ERROR: missing required TARGET variable, ex: make deploy TARGET=test-1 TAG=2018-12-17.b1"
@exit 1
endif
@echo "TODO"
\ No newline at end of file
# Prerequisites
* make
* docker
* docker-compose
# Usage
## Build and start everything
> make
## Build a single container
> make build CONTAINER=services
## Rebuild a single container (discarding docker cache)
> make rebuild CONTAINER=timber
## Run container in development mode.
This will run container in the foreground and mount source code into container to faicilitate hot-module-reloading if possible.
> make dev CONTAINER=timber
## Tag a build and push all containers
> make push TAG=b1
The current date will be prefixed to the tag, in the format YYYY-MM-DD.
It will also push the `latest` tag for all images.
# Development workflow
Always work on a branch, if your work makes the container incompatible with other containers. Otherwise, commit on master.
# TODO
* Træfic setup or some kind of named routing on localhost? (to avoid port-crashes and get more sensible adresses)
.attach*
.classpath
.env
.idea
.project
.settings
*.iml
bin
static
target
image: openjdk:10-jdk-slim
variables:
DOCKERHUB_USERNAME: deichman
before_script:
- apt-get update
- apt-get install -y apt-transport-https ca-certificates curl gnupg2 software-properties-common
- curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
- add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
- apt-get install -y docker.io maven
stages:
- build
build:
script:
- mvn package -DskipTests
- docker build -t digibib/authorization-server .
- docker tag digibib/authorization-server digibib/authorization-server:$CI_COMMIT_SHA
- docker login --username=$DOCKERHUB_USERNAME --password=$DOCKERHUB_PASSWORD
- docker push digibib/authorization-server:$CI_COMMIT_SHA
stage: build
FROM maven:3.5-jdk-10-slim AS builder
WORKDIR /app
COPY . .
RUN mvn clean package -DskipTests
FROM openjdk:10-jre-slim
WORKDIR /app
COPY --from=builder /app/target/authorization-server-0.0.1-SNAPSHOT.jar /app/
COPY ./ldap.pem /app/
ENV AUTH_SERVER_CACERTS /etc/ssl/certs/java/cacerts
RUN keytool -noprompt -storepass changeit -import -keystore ${AUTH_SERVER_CACERTS} -file /app/ldap.pem
CMD ["java", "-jar", "/app/authorization-server-0.0.1-SNAPSHOT.jar"]
-----BEGIN CERTIFICATE-----
MIID+zCCAmOgAwIBAgIMW0M3FxStRIs/Q+KRMA0GCSqGSIb3DQEBCwUAMBkxFzAV
BgNVBAMTDkxEQVAgU2VydmVyIENBMB4XDTE4MDcwOTEwMjExMVoXDTI4MDcwNjEw
MjExMVowGTEXMBUGA1UEAxMOTERBUCBTZXJ2ZXIgQ0EwggGiMA0GCSqGSIb3DQEB
AQUAA4IBjwAwggGKAoIBgQDR46Ip960b35sowNrbu3k7sMwD/kV/04eVQucFG/Uh
zYynyfZ8xxJijSuO3viarTWio81MCPhLWyhxhAUbsGi0fGBRvkiaYgGjT9t4WaCG
opzpSCUot7FddPI6HIRxjRkleD52nbziPLhkO4k/lZTUGPCOw717pOqUC7rHI0PY
TisCdivNj5TqTjTi4iqn1v1+7bjMSlTg3Rc4FrZdzhWAaJiITuHUTqLyIucYwTgR
E28ucMAsNH2JsV26EY0uGdN7fX6FS0+rD5Lwr8jGtXXObppCQ/nrAXwCVRrRVK1D
XUOTwiXiaf42wsIYi7Cm6LfQfS+Rw/JIFj8zBL0TR8tHtzEkgxv7se4by67BrVfY
MoEmh0bmIm2ewAXmmnFm9tFdTUyazXhvTMJy0/iZx++R90A0X0ni1RR51diDsYim
SI1K3Akz184yS6DEieQbyKUJg6x0s+OKweNOc/23iAL8UVvzk4tlPKUlnql/9sEe
+4tiuwNqCHPIUSWM614gQ50CAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV
HQ8BAf8EBQMDBwQAMB0GA1UdDgQWBBTr5Fa9V+J315EQJU/euVI0x8bLTzANBgkq
hkiG9w0BAQsFAAOCAYEAgBtLNKCmk1k2GTQ+Z3raiPdV5V8GDs5ErJWFkcQo6/NH
ghnd6171LAwWz1ItqeSoVqANsjlZQaeHEXUQ3EMVjJ919sKXDTvcNBw2uMPC9cai
PsJezWGHlmbo4NFT8DX/o1bIKoIohcUx+vGfU8gcGJAZXs3A2sn2diXt/oQP4jt0
oSoaLB2euzxARrNb0C858848MZHA294ejRoxtagsBTaA38YbnbOLNV8tjOzxMbOw
XvRJIX5HFi2FxVdtg0JfC5Njx0O5hSj6ZXDgmUmtC7vR2vkBTM5vzdEN07QzxhC5
lAxOWMPTk4gJI1h6fVIcg3I1TKThcFPO/rcYT9/3tPj7d5sbGRkhl1VZgachWQQL
8HMr7smWrqc7qsDk7t8WDkyUQHxH4ZSFAfgVYMz5CJlksGv42qonrdHG4UhMRgUw
fooHGCP6R5lS+1AQQzQaRsELg1S7pSDHDXF23qewPknhL16cSc3kilbphP8n6I6I
dbORJn3jKMpb3sN4iO5Q
-----END CERTIFICATE-----
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<groupId>no.deichman</groupId>
<artifactId>authorization-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>authorization-server</name>
<properties>
<java.version>1.10</java.version>
<jaxbVersion>2.3.0</jaxbVersion>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>${jaxbVersion}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${jaxbVersion}</version>
</dependency>
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.7</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-maven</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>3.3.9</version>
</requireMavenVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.5.0.1254</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version><!--$NO-MVN-MAN-VER$ -->
<configuration>
<release>10</release>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader> <!-- avoid tests crashing in CI environment -->
</configuration>
</plugin>
</plugins>
</build>
</project>
package no.deichman.auth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "no.deichman.auth")
public class DeichmanAuthServer {
public static void main(String ... args) {
SpringApplication.run(DeichmanAuthServer.class, args);
}
}
\ No newline at end of file
package no.deichman.auth.config;
import java.security.KeyPair;
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
@Configuration
@EnableAuthorizationServer
@EnableOAuth2Client
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Value("${security.oauth2.client-tjenestekatalog}")
private String clientTjenesteKatalog;
@Value("${security.oauth2.client-katalog}")
private String clientKatalog;
@Value("${security.oauth2.client-secret}")
private String clientSecret;
@Value("${security.oauth2.resource-id}")
private String resourceId;
@Value("${security.oauth2.jwt-signing-key}")
private String jwtSigningKey;
@Value("${security.oauth2.keys-jks-file}")
private String keysJksFile;
@Value("${security.oauth2.key-pair}")
private String keyPairName;
@Value("${security.oauth2.key-secret}")
private String keySecret;
private AuthenticationManager authenticationManager;
@Inject
public AuthorizationServerConfig(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyStoreKeyFactory keyStoreKeyFactory =
new KeyStoreKeyFactory(
new ClassPathResource(keysJksFile),
keySecret.toCharArray());
KeyPair keyPair = keyStoreKeyFactory.getKeyPair(keyPairName);
converter.setKeyPair(keyPair);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setTokenEnhancer(accessTokenConverter());
return defaultTokenServices;
}
@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.inMemory()
.withClient(this.clientTjenesteKatalog)
.secret(this.clientSecret)
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.scopes("read", "write")
.accessTokenValiditySeconds(1*60*60)
.refreshTokenValiditySeconds(6*60*60)
.resourceIds(this.resourceId)
.autoApprove(true)
.and()
.withClient(this.clientKatalog)
.secret(this.clientSecret)
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.scopes("read", "write")
.accessTokenValiditySeconds(1*60*60)
.refreshTokenValiditySeconds(6*60*60)
.resourceIds(this.resourceId)
.autoApprove(true);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenStore(tokenStore())
.authenticationManager(this.authenticationManager)
.accessTokenConverter(accessTokenConverter())
.tokenServices(tokenServices());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer.checkTokenAccess("isAuthenticated()");
}
}
package no.deichman.auth.config;
import java.util.Collection;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.ldap.userdetails.LdapUserDetails;
public class CustomLdapUserDetails implements LdapUserDetails {
private static final long serialVersionUID = 7728450925996668923L;
private LdapUserDetails details;
private transient DirContextOperations ctx;
public CustomLdapUserDetails(LdapUserDetails details, DirContextOperations ctx) {
this.details = details;
this.ctx = ctx;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.details.getAuthorities();
}
@Override
public String getPassword() {
return this.details.getPassword();
}
@Override
public String getUsername() {
if(this.ctx != null) {
return this.ctx.getStringAttribute("cn");
}
return this.details.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return this.details.isAccountNonExpired();
}
@Override
public boolean isAccountNonLocked() {
return this.details.isAccountNonLocked();
}
@Override
public boolean isCredentialsNonExpired() {
return this.details.isCredentialsNonExpired();
}
@Override
public boolean isEnabled() {
return this.details.isEnabled();
}
@Override
public void eraseCredentials() {
//N/A
}
@Override
public String getDn() {
return this.details.getDn();
}
}
package no.deichman.auth.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.addViewController("/").setViewName("index");
}
}
\ No newline at end of file