Commit aca34b3a authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Merge branch 'new-cluster' into 'v0.9.4'

Changed configuration and ops artifacts to reflect the new k8s cluster we use. Lots of ops artifacts where moved into the private project.

See merge request !207
parents 17c060e3 e62f63a3
Pipeline #86072 passed with stages
in 34 minutes and 13 seconds
## Containers for additional services
Some third party services cannot be used with ready made public dockerhub images. For those
we provide our own Dockerfiles that extend public base images. These are largely due to
NOMAD specific configuration that we want to apply to the the base images.
### Keycloak (optional)
A custom version of [jboss/keycloak](https://hub.docker.com/r/jboss/keycloak/)
- added bcrypt password hashing: [https://github.com/leroyguillaume/keycloak-bcrypt](https://github.com/leroyguillaume/keycloak-bcrypt)
- create admin user if not there
- import test realm on first use
- use H2 database
- change config to allow reverse proxy under custom prefix
### CI runner (optional)
This is the immage that this project uses for its gitlab-ci runner. To build an
push it, you have to log into the project's registry (see [gitlab docs](https://docs.gitlab.com/ee/user/packages/container_registry/)) and do
```
cd ci-runner
docker build -t gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-fair/ci-runner .
docker push gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-fair/ci-runner
```
This image allows to bash, git, docker, docker-compose, k8s, and helm3.
FROM docker/compose
RUN apk update && apk add --no-cache git openssh gettext
ARG VCS_REF
ARG BUILD_DATE
# Metadata
LABEL org.label-schema.vcs-ref=$VCS_REF \
org.label-schema.name="helm-kubectl" \
org.label-schema.url="https://hub.docker.com/r/dtzar/helm-kubectl/" \
org.label-schema.vcs-url="https://github.com/dtzar/helm-kubectl" \
org.label-schema.build-date=$BUILD_DATE
# Note: Latest version of kubectl may be found at:
# https://github.com/kubernetes/kubernetes/releases
ENV KUBE_LATEST_VERSION="v1.18.0"
# Note: Latest version of helm may be found at:
# https://github.com/kubernetes/helm/releases
ENV HELM_VERSION="v3.0.3"
RUN apk add --no-cache ca-certificates bash git openssh curl \
&& wget -q https://storage.googleapis.com/kubernetes-release/release/${KUBE_LATEST_VERSION}/bin/linux/amd64/kubectl -O /usr/local/bin/kubectl \
&& chmod +x /usr/local/bin/kubectl \
&& wget -q https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz -O - | tar -xzO linux-amd64/helm > /usr/local/bin/helm \
&& chmod +x /usr/local/bin/helm
WORKDIR /config
CMD bash
\ No newline at end of file
FROM jboss/keycloak:7.0.0
ARG admin_password=password
ARG prefix='fairdi\/keycloak'
USER jboss
# Change the 'web-context' to allow reverse proxy behind custom path
RUN echo "s/<web-context>auth<\\/web-context>/<web-context>$prefix\\/auth<\\/web-context>/"
RUN sed -i -e "s/<web-context>auth<\\/web-context>/<web-context>$prefix\\/auth<\\/web-context>/" $JBOSS_HOME/standalone/configuration/standalone.xml
RUN sed -i -e "s/<web-context>auth<\\/web-context>/<web-context>$prefix\\/auth<\\/web-context>/" $JBOSS_HOME/standalone/configuration/standalone-ha.xml
RUN sed -i -e "s/name=\"\\/\"/name=\"\\/$prefix\\/\"/" $JBOSS_HOME/standalone/configuration/standalone.xml
RUN sed -i -e "s/name=\"\\/\"/name=\"\\/$prefix\\/\"/" $JBOSS_HOME/standalone/configuration/standalone-ha.xml
RUN sed -i -e "s/\\/auth/\\/$prefix\\/auth/" $JBOSS_HOME/welcome-content/index.html
ENV KEYCLOAK_USER=admin
ENV KEYCLOAK_PASSWORD=$admin_password
ENV KEYCLOAK_IMPORT=/opt/jboss/keycloak/fairdi_nomad_test.json
ENV PROXY_ADDRESS_FORWARDING=true
ENV DB_VENDOR=h2
# Add exported real/client configurations
ADD ./fairdi_nomad_test.json /opt/jboss/keycloak/fairdi_nomad_test.json
ADD ./fairdi_nomad_prod.json /opt/jboss/keycloak/fairdi_nomad_prod.json
# Add a custom theme to mimic the rest of nomad's GUI
ADD ./material_theme /opt/jboss/keycloak/themes/material
# Add custom registration validation
ADD ./registration_form_action/target/form-extension-1.0-SNAPSHOT.jar /opt/jboss/keycloak/standalone/deployments/form-extension-1.0-SNAPSHOT.jar
# Additing a bcrypt password hashing algorithm to reuse old repo users
ADD ./jbcrypt-0.4.jar /tmp/jbcrypt-0.4.jar
RUN /opt/jboss/keycloak/bin/jboss-cli.sh --command="module add --name=org.mindrot.jbcrypt --resources=/tmp/jbcrypt-0.4.jar"
ADD ./keycloak-bcrypt-1.1.0.jar /opt/jboss/keycloak/standalone/deployments/keycloak-bcrypt-1.1.0.jar
## Introduction
This basically uses the "official" 7.0.0 keycloak with some additions
- material theme
- bcrypt support (https://github.com/leroyguillaume/keycloak-bcrypt/)
- a custom form action to check the username (that has to be build before building the image!)
- realm definitions for prod and test realm
- scripts for import and export of all users
## To build the image
```
cd registration_form_action
mvn package
cd ..
docker build -t nomad/keycloak .
```
## Running, Developing, Debugging
To run a keycloak container for development/test use the following. The volume mount
will allow you to edit the theme files while keycloak is running.
```
docker run -p 8002:8080 -v `pwd`/material_theme:/opt/jboss/keycloak/themes/material nomad/keycloak
```
\ No newline at end of file
docker exec -it nomad_keycloak keycloak/bin/standalone.sh \
-Djboss.socket.binding.port-offset=100 \
-Dkeycloak.migration.action=export \
-Dkeycloak.migration.provider=singleFile \
-Dkeycloak.migration.realmName=fairdi_nomad_prod \
-Dkeycloak.migration.usersExportStrategy=REALM_FILE \
-Dkeycloak.migration.file=/export/fairdi_nomad_prod_latest.json
This diff is collapsed.
This diff is collapsed.
docker exec -it nomad_keycloak keycloak/bin/standalone.sh \
-Djboss.socket.binding.port-offset=200 \
-Dkeycloak.migration.action=import \
-Dkeycloak.migration.provider=singleFile \
-Dkeycloak.migration.realmName=fairdi_nomad_prod \
-Dkeycloak.migration.strategy=OVERWRITE_EXISTING \
-Dkeycloak.migration.file=/export/fairdi_nomad_prod_latest.json
<#import "template.ftl" as layout>
<@layout.registrationLayout; section>
<#if section = "title">
${msg("Edit your NOMAD account",(realm.displayName!''))?no_esc}
<#elseif section = "header">
<div class="title">
${msg("Edit your NOMAD account",(realm.displayNameHtml!''))?no_esc}
</div>
<#elseif section = "form">
<form id="kc-register-form" class="register form ${properties.kcFormClass!}" action="${url.accountUrl}" class="form-horizontal" method="post">
<input type="text" readonly value="this is not a login form" style="display: none;">
<input type="password" readonly value="this is not a login form" style="display: none;">
<input type="hidden" id="stateChecker" name="stateChecker" value="${stateChecker}">
<input type="hidden" id="username" name="username" value="${(account.username!'')}">
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon ${properties.kcLabelClass!}">
<i class="material-icons mdc-text-field__icon" tabindex="-1" role="button">person</i>
<input required id="firstName" class="mdc-text-field__input ${properties.kcInputClass!}" name="firstName" type="text" autofocus value="${(account.firstName!'')}">
<div class="${properties.kcLabelWrapperClass!}">
<label for="firstName" class="mdc-floating-label ${properties.kcLabelClass!}">${msg("firstName")?no_esc}</label>
</div>
<div class="mdc-notched-outline">
<svg>
<path class="mdc-notched-outline__path"/>
</svg>
</div>
<div class="mdc-notched-outline__idle"></div>
</div>
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon ${properties.kcLabelClass!}">
<i class="material-icons mdc-text-field__icon" tabindex="-1" role="button">person</i>
<input required id="lastName" class="mdc-text-field__input ${properties.kcInputClass!}" name="lastName" type="text" value="${(account.lastName!'')}">
<div class="${properties.kcLabelWrapperClass!}">
<label for="lastName" class="mdc-floating-label ${properties.kcLabelClass!}">${msg("lastName")?no_esc}</label>
</div>
<div class="mdc-notched-outline">
<svg>
<path class="mdc-notched-outline__path"/>
</svg>
</div>
<div class="mdc-notched-outline__idle"></div>
</div>
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon ${properties.kcLabelClass!}">
<i class="material-icons mdc-text-field__icon" tabindex="-1" role="button">email</i>
<input required id="email" class="mdc-text-field__input ${properties.kcInputClass!}" name="email" type="text" value="${(account.email!'')}">
<div class="${properties.kcLabelWrapperClass!}">
<label for="email" class="mdc-floating-label ${properties.kcLabelClass!}">${msg("email")?no_esc}</label>
</div>
<div class="mdc-notched-outline">
<svg>
<path class="mdc-notched-outline__path"/>
</svg>
</div>
<div class="mdc-notched-outline__idle"></div>
</div>
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon ${properties.kcLabelClass!}">
<i class="material-icons mdc-text-field__icon" tabindex="-1" role="button">room</i>
<input required id="user.attributes.affiliation" class="mdc-text-field__input ${properties.kcInputClass!}" name="user.attributes.affiliation" type="text" value="${(account.attributes.affiliation!'')}">
<div class="${properties.kcLabelWrapperClass!}">
<label for="user.attributes.affiliation" class="mdc-floating-label ${properties.kcLabelClass!}">Affiliation</label>
</div>
<div class="mdc-notched-outline">
<svg>
<path class="mdc-notched-outline__path"/>
</svg>
</div>
<div class="mdc-notched-outline__idle"></div>
</div>
<div class="mdc-text-field mdc-text-field--outlined mdc-text-field--with-leading-icon ${properties.kcLabelClass!}">
<i class="material-icons mdc-text-field__icon" tabindex="-1" role="button">account_balance</i>
<input required id="user.attributes.affiliation_address" class="mdc-text-field__input ${properties.kcInputClass!}" name="user.attributes.affiliation_address" type="text" value="${(account.attributes.affiliation_address!'')}">
<div class="${properties.kcLabelWrapperClass!}">
<label for="user.attributes.affiliation_address" class="mdc-floating-label ${properties.kcLabelClass!}">Affiliation address</label>
</div>
<div class="mdc-notched-outline">
<svg>
<path class="mdc-notched-outline__path"/>
</svg>
</div>
<div class="mdc-notched-outline__idle"></div>
</div>
<div class="${properties.kcFormGroupClass!} register-button-container">
<div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
<button class="mdc-button mdc-button--raised ${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="submitAction" type="submit" value="Save">
${msg("doSave")?no_esc}
</button>
</div>
</div>
</form>
</#if>
</@layout.registrationLayout>
\ No newline at end of file
<#import "template.ftl" as layout>
<@layout.registrationLayout displayMessage=false; section>
<#if section = "title">
${msg("errorTitle")?no_esc}
<#elseif section = "header">
${msg("errorTitleHtml")?no_esc}
<#elseif section = "form">
<div id="kc-error-message">
<p class="instruction">${message.summary}</p>
<#if client?? && client.baseUrl?has_content>
<p><a id="backToApplication" href="${client.baseUrl}">${msg("backToApplication")}</a></p>
</#if>
</div>
</#if>
</@layout.registrationLayout>
\ No newline at end of file
backToLogin=Back
errorTitle=We''re sorry...
errorTitleHtml=We''re <span style="font-weight: normal">sorry</span> ...
capsLockWarning=Caps Lock is On!
\ No newline at end of file
.alert {
position: relative;
padding: 0.75rem 1.25rem;
margin-bottom: 1rem;
border: 1px solid transparent;
border-radius: 0.125rem;
}
.alert-heading {
color: inherit;
}
.alert-link {
font-weight: 700;
}
.alert-dismissible {
padding-right: 4rem;
}
.alert-dismissible .close {
position: absolute;
top: 0;
right: 0;
padding: 0.75rem 1.25rem;
color: inherit;
}
.alert-primary {
color: #004e47;
background-color: #cceae7;
border-color: #b8e2de;
}
.alert-primary hr {
border-top-color: #a6dbd6;
}
.alert-primary .alert-link {
color: #001b19;
}
.alert-secondary {
color: #383d41;
background-color: #e2e3e5;
border-color: #d6d8db;
}
.alert-secondary hr {
border-top-color: #c8cbcf;
}
.alert-secondary .alert-link {
color: #202326;
}
.alert-success {
color: #285b2a;
background-color: #dbefdc;
border-color: #cde9ce;
}
.alert-success hr {
border-top-color: #bbe1bd;
}
.alert-success .alert-link {
color: #18381a;
}
.alert-info {
color: #02587f;
background-color: #cdeefd;
border-color: #b8e7fc;
}
.alert-info hr {
border-top-color: #a0dffb;
}
.alert-info .alert-link {
color: #01354d;
}
.alert-warning {
color: #852d12;
background-color: #ffddd3;
border-color: #ffd0c1;
}
.alert-warning hr {
border-top-color: #ffbda8;
}
.alert-warning .alert-link {
color: #581e0c;
}
.alert-danger, .alert-error {
color: #7f231c;
background-color: #fdd9d7;
border-color: #fccac7;
}
.alert-danger hr, .alert-error hr {
border-top-color: #fbb3af;
}
.alert-danger .alert-link, .alert-error .alert-link {
color: #551713;
}
.alert-light {
color: #7f7f7f;
background-color: #fdfdfd;
border-color: #fcfcfc;
}
.alert-light hr {
border-top-color: #efefef;
}
.alert-light .alert-link {
color: #666;
}
.alert-dark {
color: #222;
background-color: #d9d9d9;
border-color: #cacaca;
}
.alert-dark hr {
border-top-color: #bdbdbd;
}
.alert-dark .alert-link {
color: #090909;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
@import url('https://fonts.googleapis.com/css?family=Titillium+Web:300,300i,400,400i,700,700i');
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
body {
background: #fafafa;
font-family: 'Titillium Web', sans-serif;
}
a {
color: #008DC3;
}
.title {
color: rgba(0, 0, 0, 0.87);
margin: 32px 0 16px;
font-size: 3rem;
font-family: Titillium Web,sans-serif;
font-weight: 400;
line-height: 1.167;
}
.mdc-button {
font-size: .8125rem !important;
letter-spacing: 0.02857em !important;
border-radius: 4px !important;
}
.mdc-back {
width: 560px;
margin: auto;
margin-top: 24px;
}
/* without this, the fields all expand
when the MDC JavaScript is run. */
.mdc-text-field {
margin-top: 16px;
}
#kc-header,
#kc-content {
margin-left: auto;
margin-right: auto;
}
#kc-header {
width: 90%;
font-size: 35px;
text-align: center;
margin-bottom: 25px;
font-weight: 300;
margin-top: 7%;
color: rgb(68, 68, 68);
}
#kc-content {
background: white;
padding: 20px;
box-shadow: 0 5px 6px -3px rgba(0, 0, 0, 0.2),
0 9px 12px 1px rgba(0, 0, 0, 0.14), 0 3px 16px 2px rgba(0, 0, 0, 0.12);
}
#kc-reset-password-form #kc-form-options {
float: left;
}
#kc-reset-password-form #kc-form-buttons {
float: right;
}
#kc-register-form #kc-form-options {
float: left;
}
#kc-register-form #kc-form-buttons {
float: right;
}
.clearfix {
float: none;
clear: both;
}
hr {
margin-top: 20px;
margin-bottom: 20px;
border: 0;
border-top: 1px solid rgba(0, 0, 0, 0.24);
}
@media (max-width: 768px) {
#kc-content {
width: 90%;
}
}
@media (min-width: 769px) {
#kc-content {
width: 560px;
}
}
.mdc-text-field {
width: 100%;
}
#kc-form-login #kc-form-options {
margin-top: 15px;
}
#kc-login {
float: right;
}
#kc-error-message p {
margin: 0;
}
.remember-me-checkbox {
float: left;
}
.register .register-field {
margin-bottom: 15px;
}
.register .register-button-container {
margin-top: 15px;
}
.reset-password .reset-password-field {
margin-bottom: 15px;
}
.update-password .update-password-field {
margin-bottom: 15px;
}
.update-password .update-password-button-container {
margin-top: 15px;
}
.config-totp .config-totp-button-container {
margin-top: 15px;
}
.totp .totp-button-container {
margin-top: 15px;
}
.update-profile .update-profile-field {
margin-top: 15px;
}
.update-profile .update-profile-button-container {
margin-top: 15px;
}
.template .language-picker {
position: relative;
margin: 0 auto;
margin-top: 30px;
margin-bottom: 20px;
width: 195px;
}
.template .language-picker .language-icon {
float: left;
color: rgba(0, 0, 0, 0.54);
}
.template .language-picker .mdc-select {
float: right;
margin-top: -25px;
}
.template .language-picker .mdc-select option {
font-weight: normal;
display: block;
white-space: pre;
min-height: 1.2em;
padding: 0px 2px 1px;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
window.onload = function() {
// add ripple effect to all material buttons on the page
document.querySelectorAll('.mdc-button').forEach(function(e) {
mdc.ripple.MDCRipple.attachTo(e);
});
// initialize all text fields
document.querySelectorAll('.mdc-text-field').forEach(function(e) {
new mdc.textField.MDCTextField(e);
});
// initialize all icons
document.querySelectorAll('.mdc-text-field__icon').forEach(function(e) {
new mdc.textField.MDCTextFieldIcon(e);
});
// initialize the language select box
try {
var select = new mdc.select.MDCSelect(
document.querySelector('.language-picker .mdc-select')
);