Valentin Lab
6 years ago
16 changed files with 496 additions and 8 deletions
-
72docker-registry-auth/hooks/init
-
20docker-registry-auth/hooks/pre_deploy
-
50docker-registry-auth/hooks/registry_auth-relation-joined
-
12docker-registry-auth/hooks/web_proxy-relation-joined
-
55docker-registry-auth/lib/common
-
30docker-registry-auth/metadata.yaml
-
0docker-registry-auth/src/etc/default/docker-registry
-
0docker-registry-auth/src/etc/init.d/docker-registry
-
80docker-registry/hooks/init
-
0docker-registry/hooks/install
-
8docker-registry/hooks/pre_deploy
-
13docker-registry/hooks/registry_auth-relation-joined
-
22docker-registry/hooks/web_proxy-relation-joined
-
39docker-registry/lib/common
-
95docker-registry/metadata.yaml
-
8precise/docker-registry/metadata.yaml
@ -0,0 +1,72 @@ |
|||
#!/bin/bash |
|||
|
|||
## Init is run on host |
|||
## For now it is run every time the script is launched, but |
|||
## it should be launched only once after build. |
|||
|
|||
## Accessible variables are: |
|||
## - SERVICE_NAME Name of current service |
|||
## - DOCKER_BASE_IMAGE Base image from which this service might be built if any |
|||
## - SERVICE_DATASTORE Location on host of the DATASTORE of this service |
|||
## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service |
|||
|
|||
|
|||
. lib/common |
|||
|
|||
set -e |
|||
|
|||
if [ -e "$HOST_CONFIG_FILE" ]; then |
|||
echo > "$HOST_CONFIG_FILE" |
|||
else |
|||
mkdir -p "$(dirname "$HOST_CONFIG_FILE")" |
|||
touch "$HOST_CONFIG_FILE" |
|||
fi |
|||
|
|||
init-config-add " |
|||
$SERVICE_NAME: |
|||
volumes: |
|||
- $HOST_CONFIG_FILE:$CONFIG_FILE |
|||
" |
|||
|
|||
|
|||
## |
|||
## Merge compose options |
|||
## |
|||
|
|||
service_def=$(get_compose_service_def "$SERVICE_NAME") || return 1 |
|||
options=$(e "$service_def" | shyaml -y get-value "options") || true |
|||
|
|||
if [ "$options" ]; then |
|||
while read-0 key value; do |
|||
case "$key" in |
|||
users) |
|||
user_conf=$(make_users_config "$value") || exit 1 |
|||
e "$user_conf" | ini_merge |
|||
;; |
|||
acl) |
|||
yaml_key_val_str "$key" "$value" | ini_merge |
|||
;; |
|||
*) |
|||
err "Unknown key '$key' in options." |
|||
exit 1 |
|||
;; |
|||
esac |
|||
done < <(e "$options" | shyaml key-values-0) |
|||
fi |
|||
|
|||
|
|||
## XXXvlab: ports should be not repeated (is repeated in charm metadata, or docker image) |
|||
ini_merge <<EOF |
|||
server: |
|||
addr: ":5001" |
|||
EOF |
|||
|
|||
|
|||
ini_merge <<EOF |
|||
token: |
|||
issuer: "Acme auth server" |
|||
expiration: 900 |
|||
EOF |
|||
|
|||
## Can be modified by web-proxy relation |
|||
echo "http://$SERVICE_NAME:5001" > "$SERVICE_CONFIGSTORE/etc/docker-auth/realm" |
@ -0,0 +1,20 @@ |
|||
#!/bin/bash |
|||
## Should be executable N time in a row with same result. |
|||
|
|||
set -e |
|||
|
|||
. lib/common |
|||
|
|||
|
|||
if [[ $(cat "$HOST_CONFIG_FILE" | shyaml keys) != *"_auth "* ]] && |
|||
! cat "$HOST_CONFIG_FILE" | shyaml get-value users >/dev/null; then |
|||
err "No *_auth configured and no users list provided." |
|||
exit 1 |
|||
fi |
|||
|
|||
if ! cat "$HOST_CONFIG_FILE" | shyaml get-value acl; then |
|||
err "No acl configured." |
|||
exit 1 |
|||
fi |
|||
|
|||
registry_config_hash || exit 1 |
@ -0,0 +1,50 @@ |
|||
#!/bin/bash |
|||
|
|||
set -e |
|||
|
|||
. lib/common |
|||
|
|||
LOCAL_CERTS_PATH=/etc/docker-auth/certs |
|||
|
|||
certs_path="$SERVICE_CONFIGSTORE$LOCAL_CERTS_PATH" |
|||
|
|||
mkdir -p "$certs_path" |
|||
|
|||
( |
|||
cd "$certs_path" |
|||
openssl req -x509 -newkey rsa:2048 -new -nodes \ |
|||
-keyout privkey.pem -out fullchain.pem \ |
|||
-subj "/C=FR/ST=Paris/L=Paris/O=ACME/OU=IT Department/CN=[domain.tld]" |
|||
chmod 600 privkey.pem |
|||
) |
|||
|
|||
cat <<EOF | ini_merge |
|||
|
|||
token: |
|||
certificate: "$LOCAL_CERTS_PATH/fullchain.pem" |
|||
key: "$LOCAL_CERTS_PATH/privkey.pem" |
|||
|
|||
EOF |
|||
|
|||
|
|||
config-add "\ |
|||
services: |
|||
$TARGET_SERVICE_NAME: |
|||
volumes: |
|||
- \"$certs_path:$LOCAL_CERTS_PATH:ro\" |
|||
$BASE_SERVICE_NAME: |
|||
volumes: |
|||
- \"$certs_path:$LOCAL_CERTS_PATH:ro\" |
|||
" |
|||
|
|||
|
|||
realm=$(cat "$SERVICE_CONFIGSTORE/etc/docker-auth/realm") || exit 1 |
|||
|
|||
relation-set registry-config "\ |
|||
token: |
|||
realm: \"$realm/auth\" |
|||
service: \"Docker registry\" |
|||
issuer: \"Acme auth server\" |
|||
autoredirect: false |
|||
rootcertbundle: \"$LOCAL_CERTS_PATH/fullchain.pem\" |
|||
" |
@ -0,0 +1,12 @@ |
|||
#!/bin/bash |
|||
|
|||
set -e |
|||
|
|||
. lib/common |
|||
|
|||
DOMAIN=$(relation-get domain) || exit 1 |
|||
PROTO=$(relation-get protocol) || true |
|||
PROTO=${PROTO:-https} |
|||
|
|||
|
|||
echo "$PROTO://$DOMAIN" > $SERVICE_CONFIGSTORE/etc/docker-auth/realm |
@ -0,0 +1,55 @@ |
|||
# -*- mode: shell-script -*- |
|||
|
|||
CONFIG_FILE=/etc/docker-auth/config.yml |
|||
HOST_CONFIG_FILE="$SERVICE_CONFIGSTORE$CONFIG_FILE" |
|||
|
|||
ini_merge_str() { |
|||
local cfg="$1" \ |
|||
cache_file="$CACHEDIR/$FUNCNAME.cache.$(p0 "$@" "$(cat "$HOST_CONFIG_FILE")" | md5_compat)" \ |
|||
result |
|||
if [ -z "$cfg" ]; then |
|||
return 0 |
|||
fi |
|||
if [ -e "$cache_file" ]; then |
|||
#debug "$FUNCNAME: SESSION cache hit $1" |
|||
cat "$cache_file" || return 1 |
|||
return 0 |
|||
fi |
|||
|
|||
result="$(merge_yaml_str "$(cat "$HOST_CONFIG_FILE")" "$cfg")" || return 1 |
|||
e "$result" | tee "$cache_file" || return 1 |
|||
} |
|||
|
|||
|
|||
ini_merge() { |
|||
local result |
|||
result=$(ini_merge_str "$(cat -)") |
|||
e "$result" > "$HOST_CONFIG_FILE" |
|||
} |
|||
|
|||
|
|||
make_users_config() { |
|||
local users_charm_cfg="$1" |
|||
|
|||
echo "users:" |
|||
while read-0 user config; do |
|||
echo " \"$user\":" |
|||
password="$config" |
|||
##$(e "$config" | shyaml get-value password) || return 1 |
|||
bcrypt=$(e "$password" | htpasswd -niB "$user" | cut -f 2 -d ":") |
|||
echo " password: \"$bcrypt\"" |
|||
done < <(e "$users_charm_cfg" | shyaml key-values-0) |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
registry_config_hash() { |
|||
debug "Adding config hash to enable recreating upon config change." |
|||
config_hash=$(cat "$HOST_CONFIG_FILE" | md5_compat) || exit 1 |
|||
init-config-add " |
|||
$MASTER_BASE_SERVICE_NAME: |
|||
labels: |
|||
- compose.config_hash=$config_hash |
|||
" |
|||
} |
@ -0,0 +1,30 @@ |
|||
summary: "Authentication for docker Registry" |
|||
maintainer: "Valentin Lab <valentin.lab@kalysto.org>" |
|||
docker-image: docker.0k.io/docker-registry-auth:1.3.1 |
|||
data-resources: |
|||
- /var/log/docker-auth |
|||
config-resources: |
|||
- /etc/docker-auth/ |
|||
|
|||
docker-compose: |
|||
command: /etc/docker-auth/config.yml |
|||
provides: |
|||
registry-auth: |
|||
|
|||
default-options: |
|||
# users: |
|||
# mylogin: mypasswd |
|||
# acl: |
|||
# - match: {account: "admin"} |
|||
# actions: ["*"] |
|||
# comment: "Admin has full access to everything." |
|||
# - match: {account: "user"} |
|||
# actions: ["pull"] |
|||
# comment: "User \"user\" can pull stuff." |
|||
|
|||
uses: |
|||
web-proxy: |
|||
#constraint: required | recommended | optional |
|||
constraint: recommended |
|||
solves: |
|||
proxy: "Public access" |
@ -0,0 +1,80 @@ |
|||
#!/bin/bash |
|||
|
|||
## Init is run on host |
|||
## For now it is run every time the script is launched, but |
|||
## it should be launched only once after build. |
|||
|
|||
## Accessible variables are: |
|||
## - SERVICE_NAME Name of current service |
|||
## - DOCKER_BASE_IMAGE Base image from which this service might be built if any |
|||
## - SERVICE_DATASTORE Location on host of the DATASTORE of this service |
|||
## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service |
|||
|
|||
|
|||
. lib/common |
|||
|
|||
set -e |
|||
|
|||
if [ -e "$HOST_CONFIG_FILE" ]; then |
|||
echo > "$HOST_CONFIG_FILE" |
|||
else |
|||
mkdir -p "$(dirname "$HOST_CONFIG_FILE")" |
|||
touch "$HOST_CONFIG_FILE" |
|||
fi |
|||
|
|||
init-config-add " |
|||
$SERVICE_NAME: |
|||
volumes: |
|||
- $HOST_CONFIG_FILE:$CONFIG_FILE |
|||
" |
|||
|
|||
ini_merge <<EOF || exit 1 |
|||
version: 0.1 |
|||
storage: |
|||
filesystem: |
|||
rootdirectory: /var/lib/docker-registry |
|||
|
|||
http: |
|||
addr: $SERVICE_NAME:5000 |
|||
net: tcp |
|||
host: http://$SERVICE_NAME:5000 |
|||
## XXXvlab: not used for now |
|||
#secret: asecretforlocaldevelopment |
|||
relativeurls: false |
|||
# debug: |
|||
# addr: localhost:5001 |
|||
# headers: |
|||
# X-Content-Type-Options: [nosniff] |
|||
# http2: |
|||
# disabled: false |
|||
|
|||
EOF |
|||
|
|||
|
|||
## |
|||
## Merge compose options |
|||
## |
|||
|
|||
service_def=$(get_compose_service_def "$SERVICE_NAME") || return 1 |
|||
options=$(e "$service_def" | shyaml -y get-value "options") || true |
|||
|
|||
if [ "$options" ]; then |
|||
while read-0 key value; do |
|||
case "$key" in |
|||
auth|storage|middleware|reporting|http|redis|version) |
|||
err "You should not configure '$key' in this charm." |
|||
exit 1 |
|||
;; |
|||
log|loglevel|notifications|health|proxy|compatibility|validation) |
|||
continue |
|||
;; |
|||
*) |
|||
err "Unknown key '$key' in options." |
|||
exit 1 |
|||
;; |
|||
esac |
|||
done < <(e "$options" | shyaml key-values-0) |
|||
|
|||
e "$options" | ini_merge || exit 1 |
|||
|
|||
fi |
@ -0,0 +1,8 @@ |
|||
#!/bin/bash |
|||
## Should be executable N time in a row with same result. |
|||
|
|||
set -e |
|||
|
|||
. lib/common |
|||
|
|||
registry_config_hash || exit 1 |
@ -0,0 +1,13 @@ |
|||
#!/bin/bash |
|||
|
|||
set -e |
|||
|
|||
. lib/common |
|||
|
|||
cfg=$(relation-get registry-config) || { |
|||
err "registry-auth $TARGET_SERVICE_NAME is expected to set 'registry-config'" |
|||
exit 1 |
|||
} |
|||
|
|||
yaml_key_val_str "auth" "$cfg" | ini_merge |
|||
|
@ -0,0 +1,22 @@ |
|||
#!/bin/bash |
|||
|
|||
set -e |
|||
|
|||
. lib/common |
|||
|
|||
DOMAIN=$(relation-get domain) || exit 1 |
|||
PROTO=$(relation-get protocol) || true |
|||
PROTO=${PROTO:-https} |
|||
|
|||
## These are mainly to setup the correct web-hook |
|||
if [ "$MASTER_BASE_SERVICE_NAME" == "$DOMAIN" ]; then |
|||
## This is because the IP will be the docker container version |
|||
PROTO=http |
|||
fi |
|||
|
|||
ini_merge <<EOF |
|||
|
|||
http: |
|||
host: $PROTO://$DOMAIN |
|||
|
|||
EOF |
@ -0,0 +1,39 @@ |
|||
# -*- mode: shell-script -*- |
|||
|
|||
CONFIG_FILE=/etc/docker/registry/config.yml |
|||
HOST_CONFIG_FILE="$SERVICE_CONFIGSTORE$CONFIG_FILE" |
|||
|
|||
ini_merge_str() { |
|||
local cfg="$1" \ |
|||
cache_file="$CACHEDIR/$FUNCNAME.cache.$(p0 "$@" "$(cat "$HOST_CONFIG_FILE")" | md5_compat)" \ |
|||
result |
|||
if [ -z "$cfg" ]; then |
|||
return 0 |
|||
fi |
|||
if [ -e "$cache_file" ]; then |
|||
#debug "$FUNCNAME: SESSION cache hit $1" |
|||
cat "$cache_file" || return 1 |
|||
return 0 |
|||
fi |
|||
|
|||
result="$(merge_yaml_str "$(cat "$HOST_CONFIG_FILE")" "$cfg")" || return 1 |
|||
e "$result" | tee "$cache_file" || return 1 |
|||
} |
|||
|
|||
|
|||
ini_merge() { |
|||
local result |
|||
result=$(ini_merge_str "$(cat -)") |
|||
e "$result" > "$HOST_CONFIG_FILE" |
|||
} |
|||
|
|||
|
|||
registry_config_hash() { |
|||
debug "Adding config hash to enable recreating upon config change." |
|||
config_hash=$(cat "$HOST_CONFIG_FILE" | md5_compat) || exit 1 |
|||
init-config-add " |
|||
$MASTER_BASE_SERVICE_NAME: |
|||
labels: |
|||
- compose.config_hash=$config_hash |
|||
" |
|||
} |
@ -0,0 +1,95 @@ |
|||
summary: "Docker Registry" |
|||
maintainer: "Valentin Lab <valentin.lab@kalysto.org>" |
|||
inherit: base-0k |
|||
description: | |
|||
Docker Registry |
|||
|
|||
docker-image: docker.0k.io/registry:2.0 |
|||
data-resources: |
|||
- /var/lib/docker-registry |
|||
|
|||
default-options: |
|||
# log: |
|||
# accesslog: |
|||
# disabled: true |
|||
# level: debug |
|||
# formatter: text |
|||
# fields: |
|||
# service: registry |
|||
# environment: staging |
|||
# hooks: |
|||
# - type: mail |
|||
# disabled: true |
|||
# levels: |
|||
# - panic |
|||
# options: |
|||
# smtp: |
|||
# addr: mail.example.com:25 |
|||
# username: mailuser |
|||
# password: password |
|||
# insecure: true |
|||
# from: sender@example.com |
|||
# to: |
|||
# - errors@example.com |
|||
# notifications: |
|||
# endpoints: |
|||
# - name: alistener |
|||
# disabled: false |
|||
# url: https://my.listener.com/event |
|||
# headers: <http.Header> |
|||
# timeout: 500 |
|||
# threshold: 5 |
|||
# backoff: 1000 |
|||
# ignoredmediatypes: |
|||
# - application/octet-stream |
|||
|
|||
# health: |
|||
# storagedriver: |
|||
# enabled: true |
|||
# interval: 10s |
|||
# threshold: 3 |
|||
# file: |
|||
# - file: /path/to/checked/file |
|||
# interval: 10s |
|||
# http: |
|||
# - uri: http://server.to.check/must/return/200 |
|||
# headers: |
|||
# Authorization: [Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==] |
|||
# statuscode: 200 |
|||
# timeout: 3s |
|||
# interval: 10s |
|||
# threshold: 3 |
|||
# tcp: |
|||
# - addr: redis-server.domain.com:6379 |
|||
# timeout: 3s |
|||
# interval: 10s |
|||
# threshold: 3 |
|||
|
|||
# proxy: |
|||
# remoteurl: https://registry-1.docker.io |
|||
# username: [username] |
|||
# password: [password] |
|||
# compatibility: |
|||
# schema1: |
|||
# signingkeyfile: /etc/registry/key.json |
|||
# validation: |
|||
# enabled: true |
|||
# manifests: |
|||
# urls: |
|||
# allow: |
|||
# - ^https?://([^/]+\.)*example\.com/ |
|||
# deny: |
|||
# - ^https?://www\.example\.com/ |
|||
|
|||
uses: |
|||
registry-auth: |
|||
#constraint: required | recommended | optional |
|||
constraint: recommended |
|||
solves: |
|||
unmanaged-auth: "Authentication is not managed" |
|||
|
|||
web-proxy: |
|||
#constraint: required | recommended | optional |
|||
constraint: recommended |
|||
solves: |
|||
proxy: "Public access" |
@ -1,8 +0,0 @@ |
|||
name: docker-registry |
|||
summary: "Docker Registry" |
|||
maintainer: "Valentin Lab <valentin.lab@kalysto.org>" |
|||
inherit: base-0k |
|||
description: | |
|||
Docker Registry |
|||
data-resources: |
|||
- /var/lib/docker-registry |
Write
Preview
Loading…
Cancel
Save
Reference in new issue