forked from TrueCloudLab/distribution
remove contrib folder
Signed-off-by: David van der Spek <vanderspek.david@gmail.com>
This commit is contained in:
parent
97957b12b1
commit
6fea54890d
69 changed files with 0 additions and 3235 deletions
|
@ -1,36 +0,0 @@
|
||||||
# Apache HTTPd sample for Registry v1, v2 and mirror
|
|
||||||
|
|
||||||
3 containers involved
|
|
||||||
|
|
||||||
* Docker Registry v1 (registry 0.9.1)
|
|
||||||
* Docker Registry v2 (registry 2.0.0)
|
|
||||||
* Docker Registry v1 in mirror mode
|
|
||||||
|
|
||||||
HTTP for mirror and HTTPS for v1 & v2
|
|
||||||
|
|
||||||
* http://registry.example.com proxify Docker Registry 1.0 in Mirror mode
|
|
||||||
* https://registry.example.com proxify Docker Registry 1.0 or 2.0 in Hosting mode
|
|
||||||
|
|
||||||
## 3 Docker containers should be started
|
|
||||||
|
|
||||||
* Docker Registry 1.0 in Mirror mode : port 5001
|
|
||||||
* Docker Registry 1.0 in Hosting mode : port 5000
|
|
||||||
* Docker Registry 2.0 in Hosting mode : port 5002
|
|
||||||
|
|
||||||
### Registry v1
|
|
||||||
|
|
||||||
docker run -d -e SETTINGS_FLAVOR=dev -v /var/lib/docker-registry/storage/hosting-v1:/tmp -p 5000:5000 registry:0.9.1"
|
|
||||||
|
|
||||||
### Mirror
|
|
||||||
|
|
||||||
docker run -d -e SETTINGS_FLAVOR=dev -e STANDALONE=false -e MIRROR_SOURCE=https://registry-1.docker.io -e MIRROR_SOURCE_INDEX=https://index.docker.io \
|
|
||||||
-e MIRROR_TAGS_CACHE_TTL=172800 -v /var/lib/docker-registry/storage/mirror:/tmp -p 5001:5000 registry:0.9.1"
|
|
||||||
|
|
||||||
### Registry v2
|
|
||||||
|
|
||||||
docker run -d -e SETTINGS_FLAVOR=dev -v /var/lib/axway/docker-registry/storage/hosting2-v2:/tmp -p 5002:5000 registry:2"
|
|
||||||
|
|
||||||
# For Hosting mode access
|
|
||||||
|
|
||||||
* users should have account (valid-user) to be able to fetch images
|
|
||||||
* only users using account docker-deployer will be allowed to push images
|
|
|
@ -1,127 +0,0 @@
|
||||||
#
|
|
||||||
# Sample Apache 2.x configuration where :
|
|
||||||
#
|
|
||||||
|
|
||||||
<VirtualHost *:80>
|
|
||||||
|
|
||||||
ServerName registry.example.com
|
|
||||||
ServerAlias www.registry.example.com
|
|
||||||
|
|
||||||
ProxyRequests off
|
|
||||||
ProxyPreserveHost on
|
|
||||||
|
|
||||||
# no proxy for /error/ (Apache HTTPd errors messages)
|
|
||||||
ProxyPass /error/ !
|
|
||||||
|
|
||||||
ProxyPass /_ping http://localhost:5001/_ping
|
|
||||||
ProxyPassReverse /_ping http://localhost:5001/_ping
|
|
||||||
|
|
||||||
ProxyPass /v1 http://localhost:5001/v1
|
|
||||||
ProxyPassReverse /v1 http://localhost:5001/v1
|
|
||||||
|
|
||||||
# Logs
|
|
||||||
ErrorLog ${APACHE_LOG_DIR}/mirror_error_log
|
|
||||||
CustomLog ${APACHE_LOG_DIR}/mirror_access_log combined env=!dontlog
|
|
||||||
|
|
||||||
</VirtualHost>
|
|
||||||
|
|
||||||
|
|
||||||
<VirtualHost *:443>
|
|
||||||
|
|
||||||
ServerName registry.example.com
|
|
||||||
ServerAlias www.registry.example.com
|
|
||||||
|
|
||||||
SSLEngine on
|
|
||||||
SSLCertificateFile /etc/apache2/ssl/registry.example.com.crt
|
|
||||||
SSLCertificateKeyFile /etc/apache2/ssl/registry.example.com.key
|
|
||||||
|
|
||||||
# Higher Strength SSL Ciphers
|
|
||||||
SSLProtocol all -SSLv2 -SSLv3 -TLSv1
|
|
||||||
SSLCipherSuite RC4-SHA:HIGH
|
|
||||||
SSLHonorCipherOrder on
|
|
||||||
|
|
||||||
# Logs
|
|
||||||
ErrorLog ${APACHE_LOG_DIR}/registry_error_ssl_log
|
|
||||||
CustomLog ${APACHE_LOG_DIR}/registry_access_ssl_log combined env=!dontlog
|
|
||||||
|
|
||||||
Header always set "Docker-Distribution-Api-Version" "registry/2.0"
|
|
||||||
Header onsuccess set "Docker-Distribution-Api-Version" "registry/2.0"
|
|
||||||
RequestHeader set X-Forwarded-Proto "https"
|
|
||||||
|
|
||||||
ProxyRequests off
|
|
||||||
ProxyPreserveHost on
|
|
||||||
|
|
||||||
# no proxy for /error/ (Apache HTTPd errors messages)
|
|
||||||
ProxyPass /error/ !
|
|
||||||
|
|
||||||
#
|
|
||||||
# Registry v1
|
|
||||||
#
|
|
||||||
|
|
||||||
ProxyPass /v1 http://localhost:5000/v1
|
|
||||||
ProxyPassReverse /v1 http://localhost:5000/v1
|
|
||||||
|
|
||||||
ProxyPass /_ping http://localhost:5000/_ping
|
|
||||||
ProxyPassReverse /_ping http://localhost:5000/_ping
|
|
||||||
|
|
||||||
# Authentication require for push
|
|
||||||
<Location /v1>
|
|
||||||
Order deny,allow
|
|
||||||
Allow from all
|
|
||||||
AuthName "Registry Authentication"
|
|
||||||
AuthType basic
|
|
||||||
AuthUserFile "/etc/apache2/htpasswd/registry-htpasswd"
|
|
||||||
|
|
||||||
# Read access to authentified users
|
|
||||||
<Limit GET HEAD>
|
|
||||||
Require valid-user
|
|
||||||
</Limit>
|
|
||||||
|
|
||||||
# Write access to docker-deployer account only
|
|
||||||
<Limit POST PUT DELETE>
|
|
||||||
Require user docker-deployer
|
|
||||||
</Limit>
|
|
||||||
|
|
||||||
</Location>
|
|
||||||
|
|
||||||
# Allow ping to run unauthenticated.
|
|
||||||
<Location /v1/_ping>
|
|
||||||
Satisfy any
|
|
||||||
Allow from all
|
|
||||||
</Location>
|
|
||||||
|
|
||||||
# Allow ping to run unauthenticated.
|
|
||||||
<Location /_ping>
|
|
||||||
Satisfy any
|
|
||||||
Allow from all
|
|
||||||
</Location>
|
|
||||||
|
|
||||||
#
|
|
||||||
# Registry v2
|
|
||||||
#
|
|
||||||
|
|
||||||
ProxyPass /v2 http://localhost:5002/v2
|
|
||||||
ProxyPassReverse /v2 http://localhost:5002/v2
|
|
||||||
|
|
||||||
<Location /v2>
|
|
||||||
Order deny,allow
|
|
||||||
Allow from all
|
|
||||||
AuthName "Registry Authentication"
|
|
||||||
AuthType basic
|
|
||||||
AuthUserFile "/etc/apache2/htpasswd/registry-htpasswd"
|
|
||||||
|
|
||||||
# Read access to authentified users
|
|
||||||
<Limit GET HEAD>
|
|
||||||
Require valid-user
|
|
||||||
</Limit>
|
|
||||||
|
|
||||||
# Write access to docker-deployer only
|
|
||||||
<Limit POST PUT DELETE>
|
|
||||||
Require user docker-deployer
|
|
||||||
</Limit>
|
|
||||||
|
|
||||||
</Location>
|
|
||||||
|
|
||||||
|
|
||||||
</VirtualHost>
|
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
# Docker Compose V1 + V2 registry
|
|
||||||
|
|
||||||
This compose configuration configures a `v1` and `v2` registry behind an `nginx`
|
|
||||||
proxy. By default, you can access the combined registry at `localhost:5000`.
|
|
||||||
|
|
||||||
The configuration does not support pushing images to `v2` and pulling from `v1`.
|
|
||||||
If a `docker` client has a version less than 1.6, Nginx will route its requests
|
|
||||||
to the 1.0 registry. Requests from newer clients will route to the 2.0 registry.
|
|
||||||
|
|
||||||
### Install Docker Compose
|
|
||||||
|
|
||||||
1. Open a new terminal on the host with your `distribution` source.
|
|
||||||
|
|
||||||
2. Get the `docker-compose` binary.
|
|
||||||
|
|
||||||
$ sudo wget https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` -O /usr/local/bin/docker-compose
|
|
||||||
|
|
||||||
This command installs the binary in the `/usr/local/bin` directory.
|
|
||||||
|
|
||||||
3. Add executable permissions to the binary.
|
|
||||||
|
|
||||||
$ sudo chmod +x /usr/local/bin/docker-compose
|
|
||||||
|
|
||||||
## Build and run with Compose
|
|
||||||
|
|
||||||
1. In your terminal, navigate to the `distribution/contrib/compose` directory
|
|
||||||
|
|
||||||
This directory includes a single `docker-compose.yml` configuration.
|
|
||||||
|
|
||||||
nginx:
|
|
||||||
build: "nginx"
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
links:
|
|
||||||
- registryv1:registryv1
|
|
||||||
- registryv2:registryv2
|
|
||||||
registryv1:
|
|
||||||
image: registry
|
|
||||||
ports:
|
|
||||||
- "5000"
|
|
||||||
registryv2:
|
|
||||||
build: "../../"
|
|
||||||
ports:
|
|
||||||
- "5000"
|
|
||||||
|
|
||||||
This configuration builds a new `nginx` image as specified by the
|
|
||||||
`nginx/Dockerfile` file. The 1.0 registry comes from Docker's official
|
|
||||||
public image. Finally, the registry 2.0 image is built from the
|
|
||||||
`distribution/Dockerfile` you've used previously.
|
|
||||||
|
|
||||||
2. Get a registry 1.0 image.
|
|
||||||
|
|
||||||
$ docker pull registry:0.9.1
|
|
||||||
|
|
||||||
The Compose configuration looks for this image locally. If you don't do this
|
|
||||||
step, later steps can fail.
|
|
||||||
|
|
||||||
3. Build `nginx`, the registry 2.0 image, and
|
|
||||||
|
|
||||||
$ docker-compose build
|
|
||||||
registryv1 uses an image, skipping
|
|
||||||
Building registryv2...
|
|
||||||
Step 0 : FROM golang:1.18
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
Removing intermediate container 9f5f5068c3f3
|
|
||||||
Step 4 : COPY docker-registry-v2.conf /etc/nginx/docker-registry-v2.conf
|
|
||||||
---> 74acc70fa106
|
|
||||||
Removing intermediate container edb84c2b40cb
|
|
||||||
Successfully built 74acc70fa106
|
|
||||||
|
|
||||||
The command outputs its progress until it completes.
|
|
||||||
|
|
||||||
4. Start your configuration with compose.
|
|
||||||
|
|
||||||
$ docker-compose up
|
|
||||||
Recreating compose_registryv1_1...
|
|
||||||
Recreating compose_registryv2_1...
|
|
||||||
Recreating compose_nginx_1...
|
|
||||||
Attaching to compose_registryv1_1, compose_registryv2_1, compose_nginx_1
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
5. In another terminal, display the running configuration.
|
|
||||||
|
|
||||||
$ docker ps
|
|
||||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
|
||||||
a81ad2557702 compose_nginx:latest "nginx -g 'daemon of 8 minutes ago Up 8 minutes 80/tcp, 443/tcp, 0.0.0.0:5000->5000/tcp compose_nginx_1
|
|
||||||
0618437450dd compose_registryv2:latest "registry cmd/regist 8 minutes ago Up 8 minutes 0.0.0.0:32777->5000/tcp compose_registryv2_1
|
|
||||||
aa82b1ed8e61 registry:latest "docker-registry" 8 minutes ago Up 8 minutes 0.0.0.0:32776->5000/tcp compose_registryv1_1
|
|
||||||
|
|
||||||
### Explore a bit
|
|
||||||
|
|
||||||
1. Check for TLS on your `nginx` server.
|
|
||||||
|
|
||||||
$ curl -v https://localhost:5000
|
|
||||||
* Rebuilt URL to: https://localhost:5000/
|
|
||||||
* Hostname was NOT found in DNS cache
|
|
||||||
* Trying 127.0.0.1...
|
|
||||||
* Connected to localhost (127.0.0.1) port 5000 (#0)
|
|
||||||
* successfully set certificate verify locations:
|
|
||||||
* CAfile: none
|
|
||||||
CApath: /etc/ssl/certs
|
|
||||||
* SSLv3, TLS handshake, Client hello (1):
|
|
||||||
* SSLv3, TLS handshake, Server hello (2):
|
|
||||||
* SSLv3, TLS handshake, CERT (11):
|
|
||||||
* SSLv3, TLS alert, Server hello (2):
|
|
||||||
* SSL certificate problem: self signed certificate
|
|
||||||
* Closing connection 0
|
|
||||||
curl: (60) SSL certificate problem: self signed certificate
|
|
||||||
More details here: http://curl.haxx.se/docs/sslcerts.html
|
|
||||||
|
|
||||||
2. Tag the `v1` registry image.
|
|
||||||
|
|
||||||
$ docker tag registry:latest localhost:5000/registry_one:latest
|
|
||||||
|
|
||||||
2. Push it to the localhost.
|
|
||||||
|
|
||||||
$ docker push localhost:5000/registry_one:latest
|
|
||||||
|
|
||||||
If you are using the 1.6 Docker client, this pushes the image the `v2 `registry.
|
|
||||||
|
|
||||||
4. Use `curl` to list the image in the registry.
|
|
||||||
|
|
||||||
$ curl -v -X GET http://localhost:5000/v2/registry_one/tags/list
|
|
||||||
* Hostname was NOT found in DNS cache
|
|
||||||
* Trying 127.0.0.1...
|
|
||||||
* Connected to localhost (127.0.0.1) port 32777 (#0)
|
|
||||||
> GET /v2/registry1/tags/list HTTP/1.1
|
|
||||||
> User-Agent: curl/7.36.0
|
|
||||||
> Host: localhost:5000
|
|
||||||
> Accept: */*
|
|
||||||
>
|
|
||||||
< HTTP/1.1 200 OK
|
|
||||||
< Content-Type: application/json
|
|
||||||
< Docker-Distribution-Api-Version: registry/2.0
|
|
||||||
< Date: Tue, 14 Apr 2015 22:34:13 GMT
|
|
||||||
< Content-Length: 39
|
|
||||||
<
|
|
||||||
{"name":"registry_one","tags":["latest"]}
|
|
||||||
* Connection #0 to host localhost left intact
|
|
||||||
|
|
||||||
This example refers to the specific port assigned to the 2.0 registry. You saw
|
|
||||||
this port earlier, when you used `docker ps` to show your running containers.
|
|
||||||
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
nginx:
|
|
||||||
build: "nginx"
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
links:
|
|
||||||
- registryv1:registryv1
|
|
||||||
- registryv2:registryv2
|
|
||||||
registryv1:
|
|
||||||
image: registry
|
|
||||||
ports:
|
|
||||||
- "5000"
|
|
||||||
registryv2:
|
|
||||||
build: "../../"
|
|
||||||
ports:
|
|
||||||
- "5000"
|
|
|
@ -1,6 +0,0 @@
|
||||||
FROM nginx:1.7
|
|
||||||
|
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
|
||||||
COPY registry.conf /etc/nginx/conf.d/registry.conf
|
|
||||||
COPY docker-registry.conf /etc/nginx/docker-registry.conf
|
|
||||||
COPY docker-registry-v2.conf /etc/nginx/docker-registry-v2.conf
|
|
|
@ -1,9 +0,0 @@
|
||||||
proxy_pass http://docker-registry-v2;
|
|
||||||
proxy_set_header Host $http_host; # required for docker client's sake
|
|
||||||
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_read_timeout 900;
|
|
||||||
proxy_send_timeout 300;
|
|
||||||
proxy_request_buffering off; (see issue #2292 - https://github.com/moby/moby/issues/2292)
|
|
||||||
proxy_http_version 1.1;
|
|
|
@ -1,7 +0,0 @@
|
||||||
proxy_pass http://docker-registry;
|
|
||||||
proxy_set_header Host $http_host; # required for docker client's sake
|
|
||||||
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Authorization ""; # For basic auth through nginx in v1 to work, please comment this line
|
|
||||||
proxy_read_timeout 900;
|
|
|
@ -1,27 +0,0 @@
|
||||||
user nginx;
|
|
||||||
worker_processes 1;
|
|
||||||
|
|
||||||
error_log /var/log/nginx/error.log warn;
|
|
||||||
pid /var/run/nginx.pid;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log main;
|
|
||||||
|
|
||||||
sendfile on;
|
|
||||||
|
|
||||||
keepalive_timeout 65;
|
|
||||||
|
|
||||||
include /etc/nginx/conf.d/*.conf;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
# Docker registry proxy for api versions 1 and 2
|
|
||||||
|
|
||||||
upstream docker-registry {
|
|
||||||
server registryv1:5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
upstream docker-registry-v2 {
|
|
||||||
server registryv2:5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
# No client auth or TLS
|
|
||||||
server {
|
|
||||||
listen 5000;
|
|
||||||
server_name localhost;
|
|
||||||
|
|
||||||
# disable any limits to avoid HTTP 413 for large image uploads
|
|
||||||
client_max_body_size 0;
|
|
||||||
|
|
||||||
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
|
|
||||||
chunked_transfer_encoding on;
|
|
||||||
|
|
||||||
location /v2/ {
|
|
||||||
# Do not allow connections from docker 1.5 and earlier
|
|
||||||
# docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
|
|
||||||
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
|
|
||||||
return 404;
|
|
||||||
}
|
|
||||||
|
|
||||||
# To add basic authentication to v2 use auth_basic setting plus add_header
|
|
||||||
# auth_basic "registry.localhost";
|
|
||||||
# auth_basic_user_file test.password;
|
|
||||||
# add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
|
|
||||||
|
|
||||||
include docker-registry-v2.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
include docker-registry.conf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
FROM distribution/golem:0.1
|
|
||||||
|
|
||||||
MAINTAINER Docker Distribution Team <distribution@docker.com>
|
|
||||||
|
|
||||||
RUN apk add --no-cache git
|
|
||||||
|
|
||||||
ENV TMPDIR /var/lib/docker/tmp
|
|
||||||
|
|
||||||
WORKDIR /go/src/github.com/distribution/distribution/contrib/docker-integration
|
|
|
@ -1,63 +0,0 @@
|
||||||
# Docker Registry Integration Testing
|
|
||||||
|
|
||||||
These integration tests cover interactions between registry clients such as
|
|
||||||
the docker daemon and the registry server. All tests can be run using the
|
|
||||||
[golem integration test runner](https://github.com/docker/golem)
|
|
||||||
|
|
||||||
The integration tests configure components using docker compose
|
|
||||||
(see docker-compose.yaml) and the runner can be using the golem
|
|
||||||
configuration file (see golem.conf).
|
|
||||||
|
|
||||||
## Running integration tests
|
|
||||||
|
|
||||||
### Run using multiversion script
|
|
||||||
|
|
||||||
The integration tests in the `contrib/docker-integration` directory can be simply
|
|
||||||
run by executing the run script `./run_multiversion.sh`. If there is no running
|
|
||||||
daemon to connect to, run as `./run_multiversion.sh -d`.
|
|
||||||
|
|
||||||
This command will build the distribution image from the locally checked out
|
|
||||||
version and run against multiple versions of docker defined in the script. To
|
|
||||||
run a specific version of the registry or docker, Golem will need to be
|
|
||||||
executed manually.
|
|
||||||
|
|
||||||
### Run manually using Golem
|
|
||||||
|
|
||||||
Using the golem tool directly allows running against multiple versions of
|
|
||||||
the registry and docker. Running against multiple versions of the registry
|
|
||||||
can be useful for testing changes in the docker daemon which are not
|
|
||||||
covered by the default run script.
|
|
||||||
|
|
||||||
#### Installing Golem
|
|
||||||
|
|
||||||
Golem is distributed as an executable binary which can be installed from
|
|
||||||
the [release page](https://github.com/docker/golem/releases/tag/v0.1).
|
|
||||||
|
|
||||||
#### Running golem with docker
|
|
||||||
|
|
||||||
Additionally golem can be run as a docker image requiring no additional
|
|
||||||
installation.
|
|
||||||
|
|
||||||
`docker run --privileged -v "$GOPATH/src/github.com/distribution/distribution/contrib/docker-integration:/test" -w /test distribution/golem golem -rundaemon .`
|
|
||||||
|
|
||||||
#### Golem custom images
|
|
||||||
|
|
||||||
Golem tests version of software by defining the docker image to test.
|
|
||||||
|
|
||||||
Run with registry 2.2.1 and docker 1.10.3
|
|
||||||
|
|
||||||
`golem -i golem-dind:latest,docker:1.10.3-dind,1.10.3 -i golem-distribution:latest,registry:2.2.1 .`
|
|
||||||
|
|
||||||
|
|
||||||
#### Use golem caching for developing tests
|
|
||||||
|
|
||||||
Golem allows caching image configuration to reduce test start up time.
|
|
||||||
Using this cache will allow tests with the same set of images to start
|
|
||||||
up quickly. This can be useful when developing tests and needing the
|
|
||||||
test to run quickly. If there are changes which effect the image (such as
|
|
||||||
building a new registry image), then startup time will be slower.
|
|
||||||
|
|
||||||
Run this command multiple times and after the first time test runs
|
|
||||||
should start much quicker.
|
|
||||||
`golem -cache ~/.cache/docker/golem -i golem-dind:latest,docker:1.10.3-dind,1.10.3 -i golem-distribution:latest,registry:2.2.1 .`
|
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
nginx:
|
|
||||||
build: "nginx"
|
|
||||||
ports:
|
|
||||||
- "5000:5000"
|
|
||||||
- "5002:5002"
|
|
||||||
- "5440:5440"
|
|
||||||
- "5441:5441"
|
|
||||||
- "5442:5442"
|
|
||||||
- "5443:5443"
|
|
||||||
- "5444:5444"
|
|
||||||
- "5445:5445"
|
|
||||||
- "5446:5446"
|
|
||||||
- "5447:5447"
|
|
||||||
- "5448:5448"
|
|
||||||
- "5554:5554"
|
|
||||||
- "5555:5555"
|
|
||||||
- "5556:5556"
|
|
||||||
- "5557:5557"
|
|
||||||
- "5558:5558"
|
|
||||||
- "5559:5559"
|
|
||||||
- "5600:5600"
|
|
||||||
- "6666:6666"
|
|
||||||
links:
|
|
||||||
- registryv2:registryv2
|
|
||||||
- malevolent:malevolent
|
|
||||||
- registryv2token:registryv2token
|
|
||||||
- tokenserver:tokenserver
|
|
||||||
- registryv2tokenoauth:registryv2tokenoauth
|
|
||||||
- registryv2tokenoauthnotls:registryv2tokenoauthnotls
|
|
||||||
- tokenserveroauth:tokenserveroauth
|
|
||||||
registryv2:
|
|
||||||
image: golem-distribution:latest
|
|
||||||
ports:
|
|
||||||
- "5000"
|
|
||||||
registryv2token:
|
|
||||||
image: golem-distribution:latest
|
|
||||||
ports:
|
|
||||||
- "5000"
|
|
||||||
volumes:
|
|
||||||
- ./tokenserver/registry-config.yml:/etc/docker/registry/config.yml
|
|
||||||
- ./tokenserver/certs/localregistry.cert:/etc/docker/registry/localregistry.cert
|
|
||||||
- ./tokenserver/certs/localregistry.key:/etc/docker/registry/localregistry.key
|
|
||||||
- ./tokenserver/certs/signing.cert:/etc/docker/registry/tokenbundle.pem
|
|
||||||
tokenserver:
|
|
||||||
build: "tokenserver"
|
|
||||||
command: "--debug -addr 0.0.0.0:5556 -issuer registry-test -passwd .htpasswd -tlscert tls.cert -tlskey tls.key -key sign.key -realm http://auth.localregistry:5556"
|
|
||||||
ports:
|
|
||||||
- "5556"
|
|
||||||
registryv2tokenoauth:
|
|
||||||
image: golem-distribution:latest
|
|
||||||
ports:
|
|
||||||
- "5000"
|
|
||||||
volumes:
|
|
||||||
- ./tokenserver-oauth/registry-config.yml:/etc/docker/registry/config.yml
|
|
||||||
- ./tokenserver-oauth/certs/localregistry.cert:/etc/docker/registry/localregistry.cert
|
|
||||||
- ./tokenserver-oauth/certs/localregistry.key:/etc/docker/registry/localregistry.key
|
|
||||||
- ./tokenserver-oauth/certs/signing.cert:/etc/docker/registry/tokenbundle.pem
|
|
||||||
registryv2tokenoauthnotls:
|
|
||||||
image: golem-distribution:latest
|
|
||||||
ports:
|
|
||||||
- "5000"
|
|
||||||
volumes:
|
|
||||||
- ./tokenserver-oauth/registry-config-notls.yml:/etc/docker/registry/config.yml
|
|
||||||
- ./tokenserver-oauth/certs/signing.cert:/etc/docker/registry/tokenbundle.pem
|
|
||||||
tokenserveroauth:
|
|
||||||
build: "tokenserver-oauth"
|
|
||||||
command: "--debug -addr 0.0.0.0:5559 -issuer registry-test -passwd .htpasswd -tlscert tls.cert -tlskey tls.key -key sign.key -realm http://auth.localregistry:5559 -enforce-class"
|
|
||||||
ports:
|
|
||||||
- "5559"
|
|
||||||
malevolent:
|
|
||||||
image: "dmcgowan/malevolent:0.1.0"
|
|
||||||
command: "-l 0.0.0.0:6666 -r http://registryv2:5000 -c /certs/localregistry.cert -k /certs/localregistry.key"
|
|
||||||
links:
|
|
||||||
- registryv2:registryv2
|
|
||||||
volumes:
|
|
||||||
- ./malevolent-certs:/certs:ro
|
|
||||||
ports:
|
|
||||||
- "6666"
|
|
||||||
docker:
|
|
||||||
image: golem-dind:latest
|
|
||||||
container_name: dockerdaemon
|
|
||||||
command: "docker daemon --debug -s $DOCKER_GRAPHDRIVER"
|
|
||||||
privileged: true
|
|
||||||
environment:
|
|
||||||
DOCKER_GRAPHDRIVER:
|
|
||||||
volumes:
|
|
||||||
- /etc/generated_certs.d:/etc/docker/certs.d
|
|
||||||
- /var/lib/docker
|
|
||||||
links:
|
|
||||||
- nginx:localregistry
|
|
||||||
- nginx:auth.localregistry
|
|
|
@ -1,18 +0,0 @@
|
||||||
[[suite]]
|
|
||||||
dind=true
|
|
||||||
images=[ "nginx:1.9", "dmcgowan/token-server:simple", "dmcgowan/token-server:oauth", "dmcgowan/malevolent:0.1.0", "dmcgowan/ncat:latest" ]
|
|
||||||
|
|
||||||
[[suite.pretest]]
|
|
||||||
command="sh ./install_certs.sh /etc/generated_certs.d"
|
|
||||||
[[suite.testrunner]]
|
|
||||||
command="bats -t ."
|
|
||||||
format="tap"
|
|
||||||
env=["TEST_REPO=hello-world", "TEST_TAG=latest", "TEST_USER=testuser", "TEST_PASSWORD=passpassword", "TEST_REGISTRY=localregistry", "TEST_SKIP_PULL=true"]
|
|
||||||
[[suite.customimage]]
|
|
||||||
tag="golem-distribution:latest"
|
|
||||||
default="registry:2.2.1"
|
|
||||||
[[suite.customimage]]
|
|
||||||
tag="golem-dind:latest"
|
|
||||||
default="docker:1.10.1-dind"
|
|
||||||
version="1.10.1"
|
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
# has_digest enforces the last output line is "Digest: sha256:..."
|
|
||||||
# the input is the output from a docker push cli command
|
|
||||||
function has_digest() {
|
|
||||||
filtered=$(echo "$1" |sed -rn '/[dD]igest\: sha(256|384|512)/ p')
|
|
||||||
[ "$filtered" != "" ]
|
|
||||||
# See http://wiki.alpinelinux.org/wiki/Regex#BREs before making changes to regex
|
|
||||||
digest=$(expr "$filtered" : ".*\(sha[0-9]\{3,3\}:[a-z0-9]*\)")
|
|
||||||
}
|
|
||||||
|
|
||||||
# tempImage creates a new image using the provided name
|
|
||||||
# requires bats
|
|
||||||
function tempImage() {
|
|
||||||
dir=$(mktemp -d)
|
|
||||||
run dd if=/dev/urandom of="$dir/f" bs=1024 count=512
|
|
||||||
cat <<DockerFileContent > "$dir/Dockerfile"
|
|
||||||
FROM scratch
|
|
||||||
COPY f /f
|
|
||||||
|
|
||||||
CMD []
|
|
||||||
DockerFileContent
|
|
||||||
|
|
||||||
cp_t $dir "/tmpbuild/"
|
|
||||||
exec_t "cd /tmpbuild/; docker build --no-cache -t $1 .; rm -rf /tmpbuild/"
|
|
||||||
}
|
|
||||||
|
|
||||||
# skip basic auth tests with Docker 1.6, where they don't pass due to
|
|
||||||
# certificate issues, requires bats
|
|
||||||
function basic_auth_version_check() {
|
|
||||||
run sh -c 'docker version | fgrep -q "Client version: 1.6."'
|
|
||||||
if [ "$status" -eq 0 ]; then
|
|
||||||
skip "Basic auth tests don't support 1.6.x"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
email="a@nowhere.com"
|
|
||||||
|
|
||||||
# docker_t_login calls login with email depending on version
|
|
||||||
function docker_t_login() {
|
|
||||||
# Only pass email field pre 1.11, no deprecation warning
|
|
||||||
parse_version "$GOLEM_DIND_VERSION"
|
|
||||||
v=$version
|
|
||||||
parse_version "1.11.0"
|
|
||||||
if [ "$v" -lt "$version" ]; then
|
|
||||||
run docker_t login -e $email $@
|
|
||||||
else
|
|
||||||
run docker_t login $@
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# login issues a login to docker to the provided server
|
|
||||||
# uses user, password, and email variables set outside of function
|
|
||||||
# requies bats
|
|
||||||
function login() {
|
|
||||||
rm -f /root/.docker/config.json
|
|
||||||
|
|
||||||
docker_t_login -u $user -p $password $1
|
|
||||||
if [ "$status" -ne 0 ]; then
|
|
||||||
echo $output
|
|
||||||
fi
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
# Handle different deprecation warnings
|
|
||||||
parse_version "$GOLEM_DIND_VERSION"
|
|
||||||
v=$version
|
|
||||||
parse_version "1.11.0"
|
|
||||||
if [ "$v" -lt "$version" ]; then
|
|
||||||
# First line is WARNING about credential save or email deprecation (maybe both)
|
|
||||||
[ "${lines[2]}" = "Login Succeeded" -o "${lines[1]}" = "Login Succeeded" ]
|
|
||||||
else
|
|
||||||
[ "${lines[0]}" = "Login Succeeded" ]
|
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function login_oauth() {
|
|
||||||
login $@
|
|
||||||
|
|
||||||
tmpFile=$(mktemp)
|
|
||||||
get_file_t /root/.docker/config.json $tmpFile
|
|
||||||
run awk -v RS="" "/\"$1\": \\{[[:space:]]+\"auth\": \"[[:alnum:]]+\",[[:space:]]+\"identitytoken\"/ {exit 3}" $tmpFile
|
|
||||||
[ "$status" -eq 3 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
function parse_version() {
|
|
||||||
version=$(echo "$1" | cut -d '-' -f1) # Strip anything after '-'
|
|
||||||
major=$(echo "$version" | cut -d . -f1)
|
|
||||||
minor=$(echo "$version" | cut -d . -f2)
|
|
||||||
rev=$(echo "$version" | cut -d . -f3)
|
|
||||||
|
|
||||||
version=$((major * 1000 * 1000 + minor * 1000 + rev))
|
|
||||||
}
|
|
||||||
|
|
||||||
function version_check() {
|
|
||||||
name=$1
|
|
||||||
checkv=$2
|
|
||||||
minv=$3
|
|
||||||
parse_version "$checkv"
|
|
||||||
v=$version
|
|
||||||
parse_version "$minv"
|
|
||||||
if [ "$v" -lt "$version" ]; then
|
|
||||||
skip "$name version \"$checkv\" does not meet required version \"$minv\""
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_file_t() {
|
|
||||||
docker cp dockerdaemon:$1 $2
|
|
||||||
}
|
|
||||||
|
|
||||||
function cp_t() {
|
|
||||||
docker cp $1 dockerdaemon:$2
|
|
||||||
}
|
|
||||||
|
|
||||||
function exec_t() {
|
|
||||||
docker exec dockerdaemon sh -c "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
function docker_t() {
|
|
||||||
docker exec dockerdaemon docker $@
|
|
||||||
}
|
|
||||||
|
|
||||||
# build creates a new docker image id from another image
|
|
||||||
function build() {
|
|
||||||
docker exec -i dockerdaemon docker build --no-cache -t $1 - <<DOCKERFILE
|
|
||||||
FROM $2
|
|
||||||
MAINTAINER distribution@docker.com
|
|
||||||
DOCKERFILE
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
|
|
||||||
hostname="localregistry"
|
|
||||||
installdir="$1"
|
|
||||||
|
|
||||||
install_ca() {
|
|
||||||
mkdir -p $1/$hostname:$2
|
|
||||||
cp ./nginx/ssl/registry-ca+ca.pem $1/$hostname:$2/ca.crt
|
|
||||||
if [ "$3" != "" ]; then
|
|
||||||
cp ./nginx/ssl/registry-$3+client-cert.pem $1/$hostname:$2/client.cert
|
|
||||||
cp ./nginx/ssl/registry-$3+client-key.pem $1/$hostname:$2/client.key
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
install_test_certs() {
|
|
||||||
install_ca $1 5440
|
|
||||||
install_ca $1 5441
|
|
||||||
install_ca $1 5442 ca
|
|
||||||
install_ca $1 5443 noca
|
|
||||||
install_ca $1 5444 ca
|
|
||||||
install_ca $1 5447 ca
|
|
||||||
# For test remove CA
|
|
||||||
rm $1/${hostname}:5447/ca.crt
|
|
||||||
install_ca $1 5448
|
|
||||||
install_ca $1 5600
|
|
||||||
}
|
|
||||||
|
|
||||||
install_ca_file() {
|
|
||||||
mkdir -p $2
|
|
||||||
cp $1 $2/ca.crt
|
|
||||||
}
|
|
||||||
|
|
||||||
append_ca_file() {
|
|
||||||
mkdir -p $2
|
|
||||||
cat $1 >> $2/ca.crt
|
|
||||||
}
|
|
||||||
|
|
||||||
install_test_certs $installdir
|
|
||||||
|
|
||||||
# Malevolent server
|
|
||||||
install_ca_file ./malevolent-certs/ca.pem $installdir/$hostname:6666
|
|
||||||
|
|
||||||
# Token server
|
|
||||||
install_ca_file ./tokenserver/certs/ca.pem $installdir/$hostname:5554
|
|
||||||
install_ca_file ./tokenserver/certs/ca.pem $installdir/$hostname:5555
|
|
||||||
install_ca_file ./tokenserver/certs/ca.pem $installdir/$hostname:5557
|
|
||||||
install_ca_file ./tokenserver/certs/ca.pem $installdir/$hostname:5558
|
|
||||||
append_ca_file ./tokenserver/certs/ca.pem $installdir/$hostname:5600
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIC+TCCAeGgAwIBAgIQJMzVQNYVNTbh36kZUytWiDANBgkqhkiG9w0BAQsFADAm
|
|
||||||
MREwDwYDVQQKEwhRdWlja1RMUzERMA8GA1UEAxMIUXVpY2tUTFMwHhcNMTgwNTIx
|
|
||||||
MjI1OTA2WhcNMjgwODI2MjI1OTA2WjAmMREwDwYDVQQKEwhRdWlja1RMUzERMA8G
|
|
||||||
A1UEAxMIUXVpY2tUTFMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCe
|
|
||||||
8rEU8xHh6BMYVRz/KhFftKSxS4dxJi2LoNN4fxzY6EgHNfBACt2MhIWaUSHf2YkF
|
|
||||||
NsS/T7qZWq23NEuIJYUUwbJRAh/iQsEhCI56eV+aJX+DGd2SQQNKdx1Pt528LNws
|
|
||||||
n8Ci8rEHTe6i2/U7n/DLqa32BWF3aShsVrchRgpizXezS7GLyFmhv0hi0zRKJgDG
|
|
||||||
JebLeqe/BUtEOsS/Oa65NQTEO/5EZBzM74+4eRo5zyp9Uvw4edmOrXRXK1fK9gP3
|
|
||||||
Fq/jz9+8b5eUd9vl0e9z/xTqMdicYZOUHuUtxM3hXAkkxcaVJqqqDe6URbJHpbaN
|
|
||||||
8Vt/p/csFXMWj3oSokvDAgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMB
|
|
||||||
Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCC3NiX+2Qk3WB+TRNDPCtQ7Pw+
|
|
||||||
o31SSqfF8m3fevT4mdrJqFAF4qUpDwgV9/9EkU4UBoIq03S91Dk/No0jR3VAzzRA
|
|
||||||
h3+ul/7u08JriS/ZgVediodi7H8xeCz3nvZfAwCP2ZmHzDGp39Uhc3L3WFZImZuV
|
|
||||||
fCDeSWF3c5CjJbdUuCYYFy6LwSFLPoBXZaNBL19XP9btJtjbNTm77PZJ4cELTQ+U
|
|
||||||
r5Ofw9D9mCCYrapmprw7Fw9wdE+iLL9EJCHAj7L8UYshF4+7O7Jv3ZatySMWPbjS
|
|
||||||
nIa2+eKl/sfvRvLZWV9dUSObVsm/bpv8bsHIKp4bYl+IDb2aoSWnw4eZQHDJ
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDFTCCAf2gAwIBAgIQfv/raCIVnmpXY74aUyohmDANBgkqhkiG9w0BAQsFADAm
|
|
||||||
MREwDwYDVQQKEwhRdWlja1RMUzERMA8GA1UEAxMIUXVpY2tUTFMwHhcNMTgwNTIx
|
|
||||||
MjI1OTA2WhcNMjgwODI2MjI1OTA2WjArMREwDwYDVQQKEwhRdWlja1RMUzEWMBQG
|
|
||||||
A1UEAxMNbG9jYWxyZWdpc3RyeTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
|
||||||
ggEBALedGn6gB0Km693mvJ8yz89wtfDs+SGjJi+XmJv0PYe6j5uToXQH2naXXIOZ
|
|
||||||
lT9lmXd/RciZwn50aK4T6alu96D8yeLE13P+75rdrI9DWTNHsfx0jwRxUEXNazPI
|
|
||||||
5Knwbf2MgGJfvHE6LjQ3FStJJ9f8JzryspIAYy5PJETuzoF7GsrUhgmcgQNqQcIx
|
|
||||||
d81QwOnW3EHastTPIbUxQ3cbEKZMVmvsYSY60pQuw/syN7vGcR/uJQ6HsCUWTEpk
|
|
||||||
LWFNJYudYnRIJ/mb6bGJ0tJhdlXKQ9+89oiEWZp9p1KMfyXesp8HeW8Jyoa06+Ri
|
|
||||||
5U82r0oQgC0MI5AueueoNOmQyGsCAwEAAaM6MDgwDgYDVR0PAQH/BAQDAgWgMAwG
|
|
||||||
A1UdEwEB/wQCMAAwGAYDVR0RBBEwD4INbG9jYWxyZWdpc3RyeTANBgkqhkiG9w0B
|
|
||||||
AQsFAAOCAQEAGgUESvQoD/QGZQlY2NA4sauad/yMHVo7vs5TLiKxnAfJrnP1ycD6
|
|
||||||
sqcbwCu6B1GU7fqGjKKgzXWXHTi4MiLi5bnh5Y2JBTABksGmzNAU1LbQJJkwsPnE
|
|
||||||
GBF0RgUmcw7a+4qu3TqPJABOsl+RiUQ4VDzP3DFRbyigs2li+SjLTJepahDhAke9
|
|
||||||
11lU/r3pm1cov9m0AsKSHrU777Hv5B7gmyJ1FO1Os7/KnkdHKUwiIZx0VW6Ho5H+
|
|
||||||
IiCH7iKJ1tTxe3nkwjlkSXnx7xiLOG7QK1LtTNHzBumF4COSF1kvWvIqNhJeg482
|
|
||||||
e38+Kzctl5iVbrB+JWY6roTQ26VLIdlS7A==
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpQIBAAKCAQEAt50afqAHQqbr3ea8nzLPz3C18Oz5IaMmL5eYm/Q9h7qPm5Oh
|
|
||||||
dAfadpdcg5mVP2WZd39FyJnCfnRorhPpqW73oPzJ4sTXc/7vmt2sj0NZM0ex/HSP
|
|
||||||
BHFQRc1rM8jkqfBt/YyAYl+8cTouNDcVK0kn1/wnOvKykgBjLk8kRO7OgXsaytSG
|
|
||||||
CZyBA2pBwjF3zVDA6dbcQdqy1M8htTFDdxsQpkxWa+xhJjrSlC7D+zI3u8ZxH+4l
|
|
||||||
DoewJRZMSmQtYU0li51idEgn+ZvpsYnS0mF2VcpD37z2iIRZmn2nUox/Jd6ynwd5
|
|
||||||
bwnKhrTr5GLlTzavShCALQwjkC5656g06ZDIawIDAQABAoIBAQCw7oKJYkucvpyq
|
|
||||||
x50bCyuVCVdJQhEPiNdTJRG5tjFUiUG4+RmrZaXugQx1A5n97TllHQ9xrjjtAd+d
|
|
||||||
XzLaQkP8rZsdGfFDpXXeFZ4irxNVhtDMJMVr0oU3vip/TCaMW1Kh8LIGGZrMwPOk
|
|
||||||
/S849tWeGyzycMwCRL1N8pVQl44G1aexTmlt/tjpGyQAUcGt3MtKaUhhr8mLttfL
|
|
||||||
2r6wfZgvSqReURBMdn/bf+sMKnJrYnZLRv/iPz+YWhdk4v1OXPO3D4OlYwR8HwSo
|
|
||||||
a9mOpPuC6lWBqzq8eCBU474aQw4FXaFwN08YkJKa4DqUrmadnd4o+ajvOIA4MdF5
|
|
||||||
7OOsHQaBAoGBANcVQIM6vndN2MFwODGnF8RfeLhEf46VlANkZadOOa0/igyra865
|
|
||||||
7IR4dREFFkSdte8bj6/iEAPeDzXgS4TRsZfr2gkhdXuc2NW4jTVeiYfWW3cgKfW+
|
|
||||||
7BQiHXsXCDeoZ1gXq/F5RmD8ue0TkP+IclWR52AM5e1MzfAuZzaIFNJFAoGBANqL
|
|
||||||
Q925GxuDamcbuloxQUBarXPJgBDfTWUAXAJVISy80N3av45Y0gyoNjPaU7wHNtU9
|
|
||||||
ppnYvM47o1W4qe9AkTtuU79T1WwXFr5T+4Ehm5I8WDHQwkzWGd+WlWkDidLWuvlx
|
|
||||||
ZkzwQGp3KOTJhO20lpOtCbnOa627Op/zLhCBQzLvAoGAFF4A0+x2KNoIUpkL2TfX
|
|
||||||
elMIHXrvEVN8xq11KtivgYZozjZVaSgWC51UiJ4Qs8KzfccAXklr9tHKYvGwdQ1e
|
|
||||||
YeKFrSOr+l6p8eMeDBW9tE1KMAetsYW42Vc5r3RI5OxfjOoA8EbpsTl9acPWkTwc
|
|
||||||
h5nfbSsLguMpBTt/rpxITHkCgYEAnKwwSBj25P+OXULUkuoytDcNmC+Bnxbm/hyG
|
|
||||||
2ak78j2eox26LAti8m35Ba1kUCz/01myQSLPIC5DByYutXWdaHTMlyI7o5Td2i6M
|
|
||||||
5GM6i1i1hWj6kmj+/XqPvEwsFzmXq1HvnAK0u16Xs4UAxgSr2ky35zujmFXcTmTg
|
|
||||||
xjZU/YMCgYEAqF93h8WfckZxSUUMBgxTkNfu4MJlbsVBzIHv6TJY95VA49RcRYEK
|
|
||||||
b7Xg+RiNQ42QGd8JBXZ50zQrIDhdd/yJ0KcytvW7WdiEEaF3ANO2QesygmI50611
|
|
||||||
R76F8Bj0xnoQUCbyPuMOLRfTwEaS1jBG7TKWQXTaN0fm4DxUU0KazxU=
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,192 +0,0 @@
|
||||||
#!/usr/bin/env bats
|
|
||||||
|
|
||||||
# This tests various expected error scenarios when pulling bad content
|
|
||||||
|
|
||||||
load helpers
|
|
||||||
|
|
||||||
host="localregistry:6666"
|
|
||||||
base="malevolent-test"
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
tempImage $base:latest
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test malevolent proxy pass through" {
|
|
||||||
docker_t tag $base:latest $host/$base/nochange:latest
|
|
||||||
run docker_t push $host/$base/nochange:latest
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
run docker_t pull $host/$base/nochange:latest
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test malevolent image name change" {
|
|
||||||
imagename="$host/$base/rename"
|
|
||||||
image="$imagename:lastest"
|
|
||||||
docker_t tag $base:latest $image
|
|
||||||
run docker_t push $image
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
# Pull attempt should fail to verify manifest digest
|
|
||||||
run docker_t pull "$imagename@$digest"
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test malevolent altered layer" {
|
|
||||||
image="$host/$base/addfile:latest"
|
|
||||||
tempImage $image
|
|
||||||
run docker_t push $image
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
# Remove image to ensure layer is pulled and digest verified
|
|
||||||
docker_t rmi -f $image
|
|
||||||
|
|
||||||
run docker_t pull $image
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test malevolent altered layer (by digest)" {
|
|
||||||
imagename="$host/$base/addfile"
|
|
||||||
image="$imagename:latest"
|
|
||||||
tempImage $image
|
|
||||||
run docker_t push $image
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
# Remove image to ensure layer is pulled and digest verified
|
|
||||||
docker_t rmi -f $image
|
|
||||||
|
|
||||||
run docker_t pull "$imagename@$digest"
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test malevolent poisoned images" {
|
|
||||||
truncid="777cf9284131"
|
|
||||||
poison="${truncid}d77ca0863fb7f054c0a276d7e227b5e9a5d62b497979a481fa32"
|
|
||||||
image1="$host/$base/image1/poison:$poison"
|
|
||||||
tempImage $image1
|
|
||||||
run docker_t push $image1
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
image2="$host/$base/image2/poison:$poison"
|
|
||||||
tempImage $image2
|
|
||||||
run docker_t push $image2
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
|
|
||||||
# Remove image to ensure layer is pulled and digest verified
|
|
||||||
docker_t rmi -f $image1
|
|
||||||
docker_t rmi -f $image2
|
|
||||||
|
|
||||||
run docker_t pull $image1
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
run docker_t pull $image2
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
# Test if there are multiple images
|
|
||||||
run docker_t images
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
# Test images have same ID and not the poison
|
|
||||||
id1=$(docker_t inspect --format="{{.Id}}" $image1)
|
|
||||||
id2=$(docker_t inspect --format="{{.Id}}" $image2)
|
|
||||||
|
|
||||||
# Remove old images
|
|
||||||
docker_t rmi -f $image1
|
|
||||||
docker_t rmi -f $image2
|
|
||||||
|
|
||||||
[ "$id1" != "$id2" ]
|
|
||||||
|
|
||||||
[ "$id1" != "$truncid" ]
|
|
||||||
|
|
||||||
[ "$id2" != "$truncid" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test malevolent altered identical images" {
|
|
||||||
truncid1="777cf9284131"
|
|
||||||
poison1="${truncid1}d77ca0863fb7f054c0a276d7e227b5e9a5d62b497979a481fa32"
|
|
||||||
truncid2="888cf9284131"
|
|
||||||
poison2="${truncid2}d77ca0863fb7f054c0a276d7e227b5e9a5d62b497979a481fa64"
|
|
||||||
|
|
||||||
image1="$host/$base/image1/alteredid:$poison1"
|
|
||||||
tempImage $image1
|
|
||||||
run docker_t push $image1
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
image2="$host/$base/image2/alteredid:$poison2"
|
|
||||||
docker_t tag $image1 $image2
|
|
||||||
run docker_t push $image2
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
|
|
||||||
# Remove image to ensure layer is pulled and digest verified
|
|
||||||
docker_t rmi -f $image1
|
|
||||||
docker_t rmi -f $image2
|
|
||||||
|
|
||||||
run docker_t pull $image1
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
run docker_t pull $image2
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
# Test if there are multiple images
|
|
||||||
run docker_t images
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
# Test images have same ID and not the poison
|
|
||||||
id1=$(docker_t inspect --format="{{.Id}}" $image1)
|
|
||||||
id2=$(docker_t inspect --format="{{.Id}}" $image2)
|
|
||||||
|
|
||||||
# Remove old images
|
|
||||||
docker_t rmi -f $image1
|
|
||||||
docker_t rmi -f $image2
|
|
||||||
|
|
||||||
[ "$id1" == "$id2" ]
|
|
||||||
|
|
||||||
[ "$id1" != "$truncid1" ]
|
|
||||||
|
|
||||||
[ "$id2" != "$truncid2" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test malevolent resumeable pull" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.11.0"
|
|
||||||
version_check registry "$GOLEM_DISTRIBUTION_VERSION" "2.3.0"
|
|
||||||
|
|
||||||
imagename="$host/$base/resumeable"
|
|
||||||
image="$imagename:latest"
|
|
||||||
tempImage $image
|
|
||||||
run docker_t push $image
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
# Remove image to ensure layer is pulled and digest verified
|
|
||||||
docker_t rmi -f $image
|
|
||||||
|
|
||||||
run docker_t pull "$imagename@$digest"
|
|
||||||
echo "$output"
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
FROM nginx:1.9
|
|
||||||
|
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
|
||||||
COPY registry.conf /etc/nginx/conf.d/registry.conf
|
|
||||||
COPY docker-registry-v2.conf /etc/nginx/docker-registry-v2.conf
|
|
||||||
COPY registry-noauth.conf /etc/nginx/registry-noauth.conf
|
|
||||||
COPY registry-basic.conf /etc/nginx/registry-basic.conf
|
|
||||||
COPY test.passwd /etc/nginx/test.passwd
|
|
||||||
COPY ssl /etc/nginx/ssl
|
|
||||||
COPY v1 /var/www/html/v1
|
|
|
@ -1,6 +0,0 @@
|
||||||
proxy_pass http://docker-registry-v2;
|
|
||||||
proxy_set_header Host $http_host; # required for docker client's sake
|
|
||||||
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_read_timeout 900;
|
|
|
@ -1,61 +0,0 @@
|
||||||
user nginx;
|
|
||||||
worker_processes 1;
|
|
||||||
|
|
||||||
error_log /var/log/nginx/error.log warn;
|
|
||||||
pid /var/run/nginx.pid;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log main;
|
|
||||||
|
|
||||||
sendfile on;
|
|
||||||
|
|
||||||
keepalive_timeout 65;
|
|
||||||
|
|
||||||
include /etc/nginx/conf.d/*.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Setup TCP proxies
|
|
||||||
stream {
|
|
||||||
# Malevolent proxy
|
|
||||||
server {
|
|
||||||
listen 6666;
|
|
||||||
proxy_pass malevolent:6666;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Registry configured for token server
|
|
||||||
server {
|
|
||||||
listen 5554;
|
|
||||||
listen 5555;
|
|
||||||
proxy_pass registryv2token:5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Token server
|
|
||||||
server {
|
|
||||||
listen 5556;
|
|
||||||
proxy_pass tokenserver:5556;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Registry configured for token server with oauth
|
|
||||||
server {
|
|
||||||
listen 5557;
|
|
||||||
listen 5558;
|
|
||||||
proxy_pass registryv2tokenoauth:5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Token server with oauth
|
|
||||||
server {
|
|
||||||
listen 5559;
|
|
||||||
proxy_pass tokenserveroauth:5559;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
client_max_body_size 0;
|
|
||||||
chunked_transfer_encoding on;
|
|
||||||
location /v2/ {
|
|
||||||
auth_basic "registry.localhost";
|
|
||||||
auth_basic_user_file test.passwd;
|
|
||||||
add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always;
|
|
||||||
include docker-registry-v2.conf;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
client_max_body_size 0;
|
|
||||||
chunked_transfer_encoding on;
|
|
||||||
location /v2/ {
|
|
||||||
include docker-registry-v2.conf;
|
|
||||||
}
|
|
|
@ -1,260 +0,0 @@
|
||||||
# Docker registry proxy for api version 2
|
|
||||||
|
|
||||||
upstream docker-registry-v2 {
|
|
||||||
server registryv2:5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
# No client auth or TLS
|
|
||||||
server {
|
|
||||||
listen 5000;
|
|
||||||
server_name localhost;
|
|
||||||
|
|
||||||
# disable any limits to avoid HTTP 413 for large image uploads
|
|
||||||
client_max_body_size 0;
|
|
||||||
|
|
||||||
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
|
|
||||||
chunked_transfer_encoding on;
|
|
||||||
|
|
||||||
location /v2/ {
|
|
||||||
# Do not allow connections from docker 1.5 and earlier
|
|
||||||
# docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
|
|
||||||
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
|
|
||||||
return 404;
|
|
||||||
}
|
|
||||||
|
|
||||||
include docker-registry-v2.conf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# No client auth or TLS (V2 Only)
|
|
||||||
server {
|
|
||||||
listen 5002;
|
|
||||||
server_name localhost;
|
|
||||||
|
|
||||||
# disable any limits to avoid HTTP 413 for large image uploads
|
|
||||||
client_max_body_size 0;
|
|
||||||
|
|
||||||
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
|
|
||||||
chunked_transfer_encoding on;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
include docker-registry-v2.conf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# TLS Configuration chart
|
|
||||||
# Username/Password: testuser/passpassword
|
|
||||||
# | ca | client | basic | notes
|
|
||||||
# 5440 | yes | no | no | Tests CA certificate
|
|
||||||
# 5441 | yes | no | yes | Tests basic auth over TLS
|
|
||||||
# 5442 | yes | yes | no | Tests client auth with client CA
|
|
||||||
# 5443 | yes | yes | no | Tests client auth without client CA
|
|
||||||
# 5444 | yes | yes | yes | Tests using basic auth + tls auth
|
|
||||||
# 5445 | no | no | no | Tests insecure using TLS
|
|
||||||
# 5446 | no | no | yes | Tests sending credentials to server with insecure TLS
|
|
||||||
# 5447 | no | yes | no | Tests client auth to insecure
|
|
||||||
# 5448 | yes | no | no | Bad SSL version
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5440;
|
|
||||||
server_name localhost;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localhost-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localhost-key.pem;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5441;
|
|
||||||
server_name localhost;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localhost-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localhost-key.pem;
|
|
||||||
include registry-basic.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5442;
|
|
||||||
listen 5443;
|
|
||||||
server_name localhost;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localhost-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localhost-key.pem;
|
|
||||||
ssl_client_certificate /etc/nginx/ssl/registry-ca+ca.pem;
|
|
||||||
ssl_verify_client on;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5444;
|
|
||||||
server_name localhost;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localhost-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localhost-key.pem;
|
|
||||||
ssl_client_certificate /etc/nginx/ssl/registry-ca+ca.pem;
|
|
||||||
ssl_verify_client on;
|
|
||||||
include registry-basic.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5445;
|
|
||||||
server_name localhost;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-noca+localhost-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-noca+localhost-key.pem;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5446;
|
|
||||||
server_name localhost;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-noca+localhost-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-noca+localhost-key.pem;
|
|
||||||
include registry-basic.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5447;
|
|
||||||
server_name localhost;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-noca+localhost-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-noca+localhost-key.pem;
|
|
||||||
ssl_client_certificate /etc/nginx/ssl/registry-ca+ca.pem;
|
|
||||||
ssl_verify_client on;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5448;
|
|
||||||
server_name localhost;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localhost-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localhost-key.pem;
|
|
||||||
ssl_protocols SSLv3;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add configuration for localregistry server_name
|
|
||||||
# Requires configuring /etc/hosts to use
|
|
||||||
# Set /etc/hosts entry to external IP, not 127.0.0.1 for testing
|
|
||||||
# Docker secure/insecure registry features
|
|
||||||
server {
|
|
||||||
listen 5440;
|
|
||||||
server_name localregistry;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localregistry-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localregistry-key.pem;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5441;
|
|
||||||
server_name localregistry;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localregistry-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localregistry-key.pem;
|
|
||||||
include registry-basic.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5442;
|
|
||||||
listen 5443;
|
|
||||||
server_name localregistry;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localregistry-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localregistry-key.pem;
|
|
||||||
ssl_client_certificate /etc/nginx/ssl/registry-ca+ca.pem;
|
|
||||||
ssl_verify_client on;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5444;
|
|
||||||
server_name localregistry;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localregistry-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localregistry-key.pem;
|
|
||||||
ssl_client_certificate /etc/nginx/ssl/registry-ca+ca.pem;
|
|
||||||
ssl_verify_client on;
|
|
||||||
include registry-basic.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5445;
|
|
||||||
server_name localregistry;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-noca+localregistry-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-noca+localregistry-key.pem;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5446;
|
|
||||||
server_name localregistry;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-noca+localregistry-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-noca+localregistry-key.pem;
|
|
||||||
include registry-basic.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5447;
|
|
||||||
server_name localregistry;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-noca+localregistry-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-noca+localregistry-key.pem;
|
|
||||||
ssl_client_certificate /etc/nginx/ssl/registry-ca+ca.pem;
|
|
||||||
ssl_verify_client on;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5448;
|
|
||||||
server_name localregistry;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localregistry-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localregistry-key.pem;
|
|
||||||
ssl_protocols SSLv3;
|
|
||||||
include registry-noauth.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# V1 search test
|
|
||||||
# Registry configured with token auth and no tls
|
|
||||||
# TLS termination done by nginx, search results
|
|
||||||
# served by nginx
|
|
||||||
|
|
||||||
upstream docker-registry-v2-oauth {
|
|
||||||
server registryv2tokenoauthnotls:5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 5600;
|
|
||||||
server_name localregistry;
|
|
||||||
ssl on;
|
|
||||||
ssl_certificate /etc/nginx/ssl/registry-ca+localregistry-cert.pem;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/registry-ca+localregistry-key.pem;
|
|
||||||
|
|
||||||
root /var/www/html;
|
|
||||||
|
|
||||||
client_max_body_size 0;
|
|
||||||
chunked_transfer_encoding on;
|
|
||||||
location /v2/ {
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_pass http://docker-registry-v2-oauth;
|
|
||||||
proxy_set_header Host $http_host; # required for docker client's sake
|
|
||||||
proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_read_timeout 900;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /v1/search {
|
|
||||||
if ($http_authorization !~ "Bearer [a-zA-Z0-9\._-]+") {
|
|
||||||
return 401;
|
|
||||||
}
|
|
||||||
try_files /v1/search.json =404;
|
|
||||||
add_header Content-Type application/json;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIC+TCCAeGgAwIBAgIQVhmtXJ4fG4BkISUkyZ65ITANBgkqhkiG9w0BAQsFADAm
|
|
||||||
MREwDwYDVQQKEwhRdWlja1RMUzERMA8GA1UEAxMIUXVpY2tUTFMwHhcNMTgwNTIx
|
|
||||||
MjI1MjMwWhcNMjgwODI2MjI1MjMwWjAmMREwDwYDVQQKEwhRdWlja1RMUzERMA8G
|
|
||||||
A1UEAxMIUXVpY2tUTFMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDK
|
|
||||||
J/SLv0dL7UXaNSEAdTMV8+rOFMcQNov/xLWa1mO+7zNZXHIdM+i1uQTHTdhuta6R
|
|
||||||
wfqkruPMZ9sqK7G9UIPi11ynkdTiZKRCvCr2VMc/uf5WuIsZE1JXXknSNee1TMmV
|
|
||||||
Je8TUJsRjEyQDbxn5qUAJLi8yj/O7W8wsnVHdySKMbaLN6v75151TxiIuOoncCHQ
|
|
||||||
yzz10DzjXfXYajuheu+MLy/rjNGDj0gys4yQZAHlQWY9Lsiiix9rBdXQjVc3q2QT
|
|
||||||
VM5v3pMjXcPweaIbTWJnbOgmy+267kX6kQpUfZRE55dQt6mPtPQ2idPvqPP3TXwa
|
|
||||||
AFH39cz/pPifIZApDfZFAgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMB
|
|
||||||
Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB93GckXcLcfNdg9C0xMkvByPQJ
|
|
||||||
dcy0GT991eZ/bNC39AXrmCSfn6a1FRlWoiCOSOW1NIZWQQ7jDep/T585vq2jN7KX
|
|
||||||
hT/z3iIdNWR+Amvo4pyJ93u2D3uG/bmmguAr62jyIgrJudQ3+Mnd+bj/J33XzAgc
|
|
||||||
d4ZGPvCmKtn8cTKzyS8rjy1oPSUm6pZnfk41MgMWrGuS5HkC3Aa7jo/4RdgGOJpm
|
|
||||||
nUdz2FGfW/+gwXRy2e94V7ijjz+YwpzL0wHPyXyAm7GwJ7mfvPOZrQOLLw4Z9OaK
|
|
||||||
R76t4NZBo5TmtvW5zQVsv3sPRnuqcmR0q6WR/fEuMafVtRVOVuDrZlSy0EtA
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,18 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIC+TCCAeGgAwIBAgIRAMGmTKEnobjz4ymIziTsFuMwDQYJKoZIhvcNAQELBQAw
|
|
||||||
JjERMA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE4MDUy
|
|
||||||
MTIyNTIzMVoXDTI4MDgyNjIyNTIzMVowEzERMA8GA1UEChMIUXVpY2tUTFMwggEi
|
|
||||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFrwVi+BAvng9TebwOLg2Juzg
|
|
||||||
wnW2Lv2EOqpSYmlZLLub46/W+ktqrcb+nBMBwnbON0woCbMArONuiRk7BATnmLH8
|
|
||||||
1e6I9Rax1nCaEpKhhH/b3T9PjwvzrXC+NIqeC46E7AEneAdBa4L/x27F/npLJy7X
|
|
||||||
PAwcH9ImvACJ9csIObjFnGXNTwtGA2SMIOCiNv3lpyb/Yx20EqBcj+etz8XBjAIS
|
|
||||||
46z0JDAtYAbJgIs7Ek2XQSrUud18jopzK9mrT9YvA4tDu9Woj70IXdZfOeb0W6Y+
|
|
||||||
aBbEoHvqFtyeG7BStNszM7n6CTcJAqpHOMlYQPeRjtMwb2Ffw86NvxkfrjoNAgMB
|
|
||||||
AAGjNTAzMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjAMBgNV
|
|
||||||
HRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQBv1MfAYTymtDeA62N86QFOwASq
|
|
||||||
ah2BQqfHvUzcM0U/H6YDEYUEKX2RFOtGwOwSBXr6v7JmU4KuE6tA6s+XWjD/lLr7
|
|
||||||
CqWvJfZNP6zARL+MqbZjSmyymtuXaXH4eNVgN0aaGifhUSMDsg0qyZwG8isMN4hG
|
|
||||||
kd0y1nNCn+Q3V7oe3NfjfdjviLU9PNNBQFbKRJJRQ6y267lFoWwlaHwtNyvDupVi
|
|
||||||
f+JFMiuG3o+upqBF8UFUV8Of4VL6UcJI0OoF4ngTFzn3gRYaYKmkYawUmIr9vvg7
|
|
||||||
oQccajcN1iNArnZwXK3lKSERybrUEiUZ4uZ69wVlXzE2TemhW1iYfrTU1cya
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEogIBAAKCAQEAmha8FYvgQL54PU3m8Di4Nibs4MJ1ti79hDqqUmJpWSy7m+Ov
|
|
||||||
1vpLaq3G/pwTAcJ2zjdMKAmzAKzjbokZOwQE55ix/NXuiPUWsdZwmhKSoYR/290/
|
|
||||||
T48L861wvjSKnguOhOwBJ3gHQWuC/8duxf56Sycu1zwMHB/SJrwAifXLCDm4xZxl
|
|
||||||
zU8LRgNkjCDgojb95acm/2MdtBKgXI/nrc/FwYwCEuOs9CQwLWAGyYCLOxJNl0Eq
|
|
||||||
1LndfI6KcyvZq0/WLwOLQ7vVqI+9CF3WXznm9FumPmgWxKB76hbcnhuwUrTbMzO5
|
|
||||||
+gk3CQKqRzjJWED3kY7TMG9hX8POjb8ZH646DQIDAQABAoIBAE2SfnOWbHoLqXqr
|
|
||||||
WkS7OTnB1OS94Qarl2NXKWG6O3DyTSyIroBal1cITzLkncj3/lmIiyVo5J3Fa+W8
|
|
||||||
zV/hgRqay5gOlzyJrjgvTZazHPCFRN0KABJsYEb3nNeUmehAxynxqg8VpQlxN4zO
|
|
||||||
+NxiZWyqODGRAEO0XVa0tMy/Wcw0guD18+U9GYiYQi3d7NEHTt5d8CX9VKY/bHKR
|
|
||||||
+ecC/lr7URnA/8FM60mKI6MAiHPxyUjJ7/6dq1goG8dDHcAtOEEIawECQtRfQ+Dn
|
|
||||||
RL55nDPRYNviXRgr8u61TFm8zgkTUQy2MLRkHAyP0IBLUiMpqDdmXB4LNMQQSrsY
|
|
||||||
0FyinIECgYEAy3eT5ZUb/ijGsWUT/DizUoetFfg8X4LV+HRLXdlxfcOYB3Elbeks
|
|
||||||
JPC+Tdm33nB0lqo3hLVNPB9yqJiPOOaWQPpWBImOeitpmDRAagjwUewJwLY9RmKT
|
|
||||||
RD0+YyCC0SwvSDFDsWF+ncW/8XpobvetCSC6mmjX6Wr070yHkhDeeC0CgYEAwd9v
|
|
||||||
P+TjgWVyL5YRiOJ+wjR7ZKpHCiSSxSTjIhq40hs5LtHddSk9e/+AU0otcMExzCqN
|
|
||||||
E4f/e05a6TD5CFAgmUMK7nb49ept3ENVoD+M13K3tTaTyeZghwYNNK56osDtdCgc
|
|
||||||
c68jQAy81gU7iRt30xbLVV6HgGdrSrWN8D8DFWECgYABkV1RYpHBppzJVycNRX6U
|
|
||||||
PzllNvF4JvDxJixCf99xAaXVQNjx/N77NeOxg+D31NQBKTSeUCtVMETY6bwIyzYT
|
|
||||||
MBqjlE/FvznkE1r/tivr5a65jm3wcegCmZo2d1SqufVvT/nejwrDunddK/1MBZqO
|
|
||||||
vHLTp8UqJknW4jcVOA4OzQKBgG7BdozJ9i62BcWptdq9iizoTpXzsSHaQv7dU+Tn
|
|
||||||
3y4o30IgIqQMK1PrYyQx/EOuGwTISlAeIZYP7V/K2nolTHpCEryouxHCG4D59rDV
|
|
||||||
nWB36PtdcpClS//XNTQjeWwBS6ZQQ/DS3RB6NmcOFjT9vDabjw32MvLoIiNMFQpq
|
|
||||||
9RgBAoGARQnQ94oH98m/iheJpzaM9NhQhAoXSi4w19FySCtnyZTYTd0A7hjRzsSl
|
|
||||||
DeoAkIGDHyy33RPK/kPtA6dxM/DQ00IkkwH4soaDDbnCmagdw4NnY8eA1Y/KSbd+
|
|
||||||
XNNm+sDafoVyCojtsTA7bripKB8q5vPYo3qRLfQ7dwMeRPYblPI=
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDDTCCAfWgAwIBAgIQfzdVwVz4igfdJPd6SW/ENTANBgkqhkiG9w0BAQsFADAm
|
|
||||||
MREwDwYDVQQKEwhRdWlja1RMUzERMA8GA1UEAxMIUXVpY2tUTFMwHhcNMTgwNTIx
|
|
||||||
MjI1MjMwWhcNMjgwODI2MjI1MjMwWjAnMREwDwYDVQQKEwhRdWlja1RMUzESMBAG
|
|
||||||
A1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
||||||
v+H3BTOGLRYjyPx+JQQcP5r8HHBmjknflE6VcrbRD5VGx8192hwsjAdlL0kz1CEq
|
|
||||||
FW2KQidJieDi8iIh9BWB8lsTQ51xZGnry6CbVXxTbv1Ss8ci9r8Cm3GPjWy5gqTi
|
|
||||||
DTUUQez8xq29gUod4ZvRoJ8jl/eI7gF7MBFakv7tZQ40SHcogjQoG7nKMXG1VOhX
|
|
||||||
D4kM120E+hW9x0U3j0SaCIYl6bG2RHIvUMlrVnj4es6JBVzqItkhAwugE6ytneOh
|
|
||||||
VxWQ/7e8qKW2+lVsPnH/zjNES0j/9XYgVCjwkgirxjs2eZRIS5Mg14DdYqfQ9MRQ
|
|
||||||
EoyQxl3xcDxjqPocMgGYHwIDAQABozYwNDAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0T
|
|
||||||
AQH/BAIwADAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEB
|
|
||||||
ACU0E2BAdqjVvO06ZyHplxxQ4TQxK9voBCTheC2G7oFaM4VLFf48GgoMkvbsMGyd
|
|
||||||
1JqIACCDuSJ5UVjmWm6VIDZrnRsf/BbQCTZXKQd4ONLL5DU/OPjAFKGeCpAK51yj
|
|
||||||
OMHdw3cQmMCEpMH9HHJ+iB3XWLcDKPAxTkcsBytC9VLUgU7Q4+3eYIT/j/ug+y4G
|
|
||||||
W4A0cmdDDuozwBAPXj7ZLKdVlkUFka8WjQAJesHTIifS1bfahGiSNVJbYjXbGoML
|
|
||||||
d0IeGMd1lXlc2M+ygqZsSM2ErzndNdvDs7S6u/FIICm7uW6P2naPeMtedb2orO6Q
|
|
||||||
5O3gRtj/UQjegI0XV4YO2TQ=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEAv+H3BTOGLRYjyPx+JQQcP5r8HHBmjknflE6VcrbRD5VGx819
|
|
||||||
2hwsjAdlL0kz1CEqFW2KQidJieDi8iIh9BWB8lsTQ51xZGnry6CbVXxTbv1Ss8ci
|
|
||||||
9r8Cm3GPjWy5gqTiDTUUQez8xq29gUod4ZvRoJ8jl/eI7gF7MBFakv7tZQ40SHco
|
|
||||||
gjQoG7nKMXG1VOhXD4kM120E+hW9x0U3j0SaCIYl6bG2RHIvUMlrVnj4es6JBVzq
|
|
||||||
ItkhAwugE6ytneOhVxWQ/7e8qKW2+lVsPnH/zjNES0j/9XYgVCjwkgirxjs2eZRI
|
|
||||||
S5Mg14DdYqfQ9MRQEoyQxl3xcDxjqPocMgGYHwIDAQABAoIBABbp0ueqGXG03R0Z
|
|
||||||
Ga8t6Hmn9kcnHPgM1kgNgkcqkZh8yPD/FvI+vwsRrwGQikHgm/fnFsWDj4KJelBT
|
|
||||||
xx4wm03nlktSt8G37FJqoWH58LSmR4P0WbaBZLxPOUc4Hob9TYkqN3sP47eN871G
|
|
||||||
rn7MbqHxnvx8sLtLLfy1dc1r58lTTZB7YL1OPV7B/VYhYFDtpkUBvadV+WJ7SJ5G
|
|
||||||
UHrBsshOUJbUI4ahmc8izi40yDw+A0LRhtj3i7aFr2Og+vCq9M8NXDjhdOu9VBkI
|
|
||||||
fvniC6worJk/GnQDJ/KT5Uqfejdd3Pq7eHp11riqwua8+/wi726zRz9perFh/3gJ
|
|
||||||
pYjaY+ECgYEA+ssW+vJRZNHEzdf8zzIJxHqq9tOjbQK9yyIPQP5O4q9zKvDJIpnX
|
|
||||||
T31aZTLGy0op+XA9GJ7X0/d1tqo3G2wNBsFYWPn3gmVVth/7iHxRznorNfmsuea7
|
|
||||||
1gFm19StL2+q8PaZ4fx9vUcWwDHlALYTYlTaazms6z9FWD/KbB8kiWkCgYEAw93H
|
|
||||||
Pp12ND3f6p2rYbXPfHJ0aAUbrQR4wRG3ipVWXGjvn2h/CbrLAt5W1wB3iwnWwatX
|
|
||||||
opdbfzjxgb0wRQHSPNVj3/SOHr8E5zH/mw+eV7mOea4xlCLTSIAJNzW1320hwsbw
|
|
||||||
FrEC5qe41PrbMUu+4LvXPkHCKVxRXaV4QX4YHEcCgYEAurjegTRM+X1cw81dwn4E
|
|
||||||
265g/6iO8qip2kWficpNvWTXoE7p0cMslVhFJzdo3w52teqk8mHBW2XQ1JFiuh32
|
|
||||||
jOMC/iwN5Z3A9PpW8kVtOwemiGc9/KMXkrw0b9k+oCTJ5uITrDeq/nOhMrNzRtZJ
|
|
||||||
FFsMy+yDHBtda9kCwwFk2JECgYBQUpbu+qwK6IT3NgmeXGzmYBmUvuOGpJrQsm9O
|
|
||||||
iceMxgvel3/hgZTXbE64hRyBDFvhuF6L8v42widoSSmOYxzQjcITibruqO9d0Ic+
|
|
||||||
E72fxBzFkcYLNezngnpFBeW75ok900+KPrUt2gJWdTmGkcWJa/7tLRJu28kSWlVi
|
|
||||||
pk9E6QKBgDH2Uh61ToeNq8Gbnue3pnhUddHELRFQfwHHaa4tFrXBHuPLKqkVefKT
|
|
||||||
A58awVoPpKTECROeyqe2DJXg9EdSVzKyhg217N/07NRaunfCJ9/TSpFy+5Xls7Rl
|
|
||||||
U7zK25S1/13KZ6rGVHpmP6Q82VSnsHkPtUfDo3A29llqIQ8je43Y
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDFTCCAf2gAwIBAgIQM3khHYh+82EC0qR1Pelk2DANBgkqhkiG9w0BAQsFADAm
|
|
||||||
MREwDwYDVQQKEwhRdWlja1RMUzERMA8GA1UEAxMIUXVpY2tUTFMwHhcNMTgwNTIx
|
|
||||||
MjI1MjMxWhcNMjgwODI2MjI1MjMxWjArMREwDwYDVQQKEwhRdWlja1RMUzEWMBQG
|
|
||||||
A1UEAxMNbG9jYWxyZWdpc3RyeTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
|
||||||
ggEBAKA8e9cUSyasRtEHw3yGW5lFCnnZIN+SSvykAOynt9LLKzU5G5ge3ekBtzsl
|
|
||||||
HE1ndeYjy/dK7XkECQBQ0csF+KSacU5QiZek8g6btH94HDwltCq1I8f1E8LQFP6k
|
|
||||||
483MKZUDeNNnHzbuK9xsMjYOCrJWGysLHnKjzK/+yfVPwTm9tmUVRqd4xjw1oYY6
|
|
||||||
C7iCffIWn7+dQKDjHrn+KyheIy244v5y63AaxgPfjHrtvJtz1vPqxi+FyzDM7RfZ
|
|
||||||
GIjklC6KaKHmxvUsB0hO4WNb9kt8FBvnxOxuDKf+rUYKTg6JK72O3TaUauiEvE2X
|
|
||||||
SKT0vYpLoep5hc9ns/yh3BuuznECAwEAAaM6MDgwDgYDVR0PAQH/BAQDAgWgMAwG
|
|
||||||
A1UdEwEB/wQCMAAwGAYDVR0RBBEwD4INbG9jYWxyZWdpc3RyeTANBgkqhkiG9w0B
|
|
||||||
AQsFAAOCAQEAMt/lnR3Wy99X/knvjtg7wsPz5T9sZ5hGy/9sIm8sFdsqt5NZi9IY
|
|
||||||
vS+eyij1yHvOU+pqOxsYQ2NG26CS0CKM3JWLJTo/w8GyiSwxL8a1/UxHmTxDnSMH
|
|
||||||
cYZRsuPtdkTiAuZhoT5I1ZTsOa7MQF25HiFBL6Ei88FFhcQQjJ7+xYDNhSoddMtz
|
|
||||||
U8mUY6NOENmvE86QMjWjaj1PXPLO8PxPIqw482Ln/95pHzuaxAYMvxhs2aQlBS1/
|
|
||||||
9+vi6VOkbQna9+crmzniXjZDx5QdvMN2QwzFL4hCgqbebVg0zwjhByOwQIjtNEXE
|
|
||||||
gqxjLkTNOdSva6Fkk/z8BD2XSZ4L+nM3Mw==
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEogIBAAKCAQEAoDx71xRLJqxG0QfDfIZbmUUKedkg35JK/KQA7Ke30ssrNTkb
|
|
||||||
mB7d6QG3OyUcTWd15iPL90rteQQJAFDRywX4pJpxTlCJl6TyDpu0f3gcPCW0KrUj
|
|
||||||
x/UTwtAU/qTjzcwplQN402cfNu4r3GwyNg4KslYbKwsecqPMr/7J9U/BOb22ZRVG
|
|
||||||
p3jGPDWhhjoLuIJ98hafv51AoOMeuf4rKF4jLbji/nLrcBrGA9+Meu28m3PW8+rG
|
|
||||||
L4XLMMztF9kYiOSULopooebG9SwHSE7hY1v2S3wUG+fE7G4Mp/6tRgpODokrvY7d
|
|
||||||
NpRq6IS8TZdIpPS9ikuh6nmFz2ez/KHcG67OcQIDAQABAoIBABNXmb9ZtMSjUR0U
|
|
||||||
adWTRmVW/y+8NQqn1yNuDKqEiF0Kp1mSXjFbsH/a9CpQjX0Oex3fvlRImCfeg9Ok
|
|
||||||
7d4rB1ufRQQmFqXWhF2dEAm/DvF3v6rUGNCfVdZTVeVzNAh4l6BkPeaO8SapU2QV
|
|
||||||
L250/XePi1ID0pYWDbRE9k4FZZa5je3mTctn3s1PHp6xxQdyDHfxZmCZImwZcErj
|
|
||||||
joBoQldvUUfjqXCY9SgRJ/MQSNeJoJvPwXmYokpqxfv2sP+JlQgXEcO3Ihj9IkGx
|
|
||||||
avMFR3yGdWWLxmE3zzypXvFI+My0E035fEjcObspVOgqxJJUCWLSwWtVAo9shFgO
|
|
||||||
fPnfv70CgYEAxqVNQ4eEf8HRDN7Ygr9yruqN5NxXKJKBqOT+OlTAiCtrm6iRFkR/
|
|
||||||
WOFA3Ewjk5dxnVBvXHhTZoS2yfIVj8Pz7wbcoigfT+ia4JcAW8xQTs1CV/Xz8JsN
|
|
||||||
ChUH3ee2POue/AAxf25yDBGH3fKq34aqL9WNDmaUz+hDCo4r3/hfVZ8CgYEAzoAv
|
|
||||||
tBxwE/VUwkmWzv40WI9J4GSh7lYo4d8Z2TR6FRSxgb0Uf3C3GiGKuLf9EMilL3ae
|
|
||||||
i/Dsb0CVn2sfLdSNFlxj1l8V4R8JfXST2Tn4g1pv6Hs3LEXJtlncg5/1DiMtfrqW
|
|
||||||
quJtKuv8xO+5rbfqtmMYduf4ELkwg1uJJBc/we8CgYBZkUMrRbl6mXuXIAvjuEsP
|
|
||||||
j3b3UFqEUrrf2pC+4GQHgfx9LR5uOehpvPcv3azU6Z4y3oe33BFO0lxQ5jTOo/4j
|
|
||||||
Mqbc/tZPg4QB7FQfEBrNzUMywhWB0Yepmh338nh7M4p1+ehXmwcVZforGzXsn52w
|
|
||||||
/8sgSSSkMge4hK5HyIfD5QKBgHVr6rROH2UZ8dJwqfKWFgntoKKaVoICOEkH5dje
|
|
||||||
wDTQiYcuj0NQQq33OLyE0sACd/ufRdRpcOhqHyqBbT9QR9HZQ2QYuYZDcdAGxDOX
|
|
||||||
hTqb6FqYBe2E2Yh5XKzz/hLF6g7P5vDQxCbN/fO2JS0lEbAYdUbX7PUFeRKYsEj3
|
|
||||||
d2e9AoGAMrejS2Ic64k2I8VyYapEJ1SUaCeNCj7yR67QVtXJWvmYeu9tsUy9bxGC
|
|
||||||
FmZuEIUnQV5KZUCKG26GKq/0NiT0Umc38zlUSJzDVM9LUHEt5K066RhVEBp3Fds5
|
|
||||||
VIGgI1BkHeMKfhve0wwAbFECL+rzC9ihb6uNxZywlfeyfKN6ga8=
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,18 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIC+DCCAeCgAwIBAgIQTCXTJncsLpgueaMqQF6AiTANBgkqhkiG9w0BAQsFADAm
|
|
||||||
MREwDwYDVQQKEwhRdWlja1RMUzERMA8GA1UEAxMIUXVpY2tUTFMwHhcNMTgwNTIx
|
|
||||||
MjI1NzI4WhcNMjgwODI2MjI1NzI4WjATMREwDwYDVQQKEwhRdWlja1RMUzCCASIw
|
|
||||||
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL0fYn9wE7phMA6CFT6gv7mDpzSB
|
|
||||||
LkebCxj3LfU/isdgXvtXUn+BKIolvav7oJyTyz1R0NzX5uXxEERMBUW89KWvPLPK
|
|
||||||
o3d47MWMcAgiYx2+FeGZo1cjq3IRVKyg3WRVw2rO0YNL3K1QCS93A+IdA/05muwt
|
|
||||||
346XJ2FV0tPmETn6t+So2e9ZXh+uJjcCHq4XpJAJznCwemzzRpDe7nG5sYZqq+Oz
|
|
||||||
zBQ/bTC8rOdqW5woH/GhQHYHcKf1taPLmDLczVPQCqS3LAEK5EOUElfpQykfkZI4
|
|
||||||
clOZBhJ0e5zNEBTB/XRd7uuUA57Ig58l7hbX0fUPHgS9MF1z9CXJ40BSm/sCAwEA
|
|
||||||
AaM1MDMwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1Ud
|
|
||||||
EwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAHKH54KZdpvcLRIJK4yeSqwOigYp
|
|
||||||
0NHM9U8RlHjmf5Tp9lCtZpVrkfUtg9rXytekAXfd6GaNex7swTMNPnJBGgaQ2vA8
|
|
||||||
0jdtKfe6AcHTYQV1rs0qunlR8i26cNhYblKPJjYYA6FBzTTtybXhHYG9xvYpSVpo
|
|
||||||
XcrsC81DYK6nMiQMRYuT7RO/rtI4Tzx+laYc0lYgBzf6pXUjXycgAuJ5+cWT8DDn
|
|
||||||
OxPXbfAxfzc6jYfsigwzdOCnuIomFogm8ad47ApTTTLFrVtqCNJAKCu7HufEbB2G
|
|
||||||
OKWvl9NmTPYetS6MO5LqLAWcf/uRPn+lufHeTfBWIDD5zbJ2+ATP+mQQ2d0=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEAvR9if3ATumEwDoIVPqC/uYOnNIEuR5sLGPct9T+Kx2Be+1dS
|
|
||||||
f4EoiiW9q/ugnJPLPVHQ3Nfm5fEQREwFRbz0pa88s8qjd3jsxYxwCCJjHb4V4Zmj
|
|
||||||
VyOrchFUrKDdZFXDas7Rg0vcrVAJL3cD4h0D/Tma7C3fjpcnYVXS0+YROfq35KjZ
|
|
||||||
71leH64mNwIerhekkAnOcLB6bPNGkN7ucbmxhmqr47PMFD9tMLys52pbnCgf8aFA
|
|
||||||
dgdwp/W1o8uYMtzNU9AKpLcsAQrkQ5QSV+lDKR+RkjhyU5kGEnR7nM0QFMH9dF3u
|
|
||||||
65QDnsiDnyXuFtfR9Q8eBL0wXXP0JcnjQFKb+wIDAQABAoIBAGQFxk1KFFT9c7Io
|
|
||||||
oF3IHL5b38HIFJbwbBUfHaJYoehCktlxXINs5ujxfvgHk/FbxSDANaunUEoKjaTh
|
|
||||||
Y+R3RBigroUURhI41VjBprrWnP8s+lufqyC6D8G7YsIOLikTps/FZE+Bfsv2yXTe
|
|
||||||
CCK9X8+8eLAyrsq2LLCw+Fjzk+bKRj+zE1bUR2MqNYtRNOFizDR0DCy/f+OltmhR
|
|
||||||
MVTQgA4hAWyCXc3c07zJ3YMiVMHBIGX3hiwEGhzgKtS8vQ7isW21StGLsMQlvUgt
|
|
||||||
AjrVzzsacCSzuL+QZoZtZl3E7V/Mko0bKNeOz2ouoWTKxInlzget+b+zE39+1WZO
|
|
||||||
T/X54gkCgYEAx5sI73letGuk9DOopwKLokj0Qdj3f5VRb3yJqbp3YkLTeayyRAwD
|
|
||||||
3KY+NwSDGLqj/IcG5DN/ZtLbbhiI2F3oPcJG8QyVqmsfzF7aW3RaBBt6gFN6IdQ9
|
|
||||||
SO0pS28bj3PVLqPqx3gXHZ3l9WRgj5mbl6yvoICiymMMKajOgKi0sTcCgYEA8o4j
|
|
||||||
+0HFhxcLvPz8GCynSarMXaZe/mEImURq8ObH2KSgBogD5mCA3IHL4kQSiRyxNoAt
|
|
||||||
crGr1idsR28UYfX4xprMp3okA9ujAw0hkiNhUh3jf3ZywvQXFkOoSbtwnfAFK83c
|
|
||||||
CmHy+c4OL9BAXsHvhsRHDCVjfKupqJQwux+9HV0CgYB+FSMmyX6V7qzqiDsPC5+S
|
|
||||||
Kg0IDvn/QB2Jk5wNdzhz/AxC/mA4dXJ3DRedfx8kHrj5CX3D5feixqxOtfay3VaW
|
|
||||||
tEJFfxKG7FXQrVW2kR9PGuBdcN1jwwHXL992w78f9SYC6Q2jY+sODTA1umr4KipL
|
|
||||||
O4xQkRDDUJ9dLUELqgVBLwKBgQC+/CLizQgOdZv9hCmvk0FppP3j44M6wwa1QAUA
|
|
||||||
iIblU8LZQbHobSYp+l2iXL1HjvsOkeC3RaSrLEF7AcDH3Zi0MOFiIa9IBmIVnfpI
|
|
||||||
Cmmv8e7Wx1pXnUCsfDt/SwLCqWI4+o/+8N8TySasiUqWEhhbQiM7Mhli6fvdzEmO
|
|
||||||
ndAX1QKBgCKJA25iPkLKw4mFVxAaPIAZnenJXJpuHF9tGzjjcFfioGtvI/1mrePs
|
|
||||||
PhwoO1qpjzY9brtf47l+vVMSY9KrA1LvudPvTqBtyjQvG5SqsWZSLuyJL30HKeFy
|
|
||||||
hv9FCsGVcF6wu3S8wXaGC/H8kityxTqFgZQW5whl2D9axJavygKj
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDDjCCAfagAwIBAgIRAI0Dt8LVd8cJPc0dv5aW+wcwDQYJKoZIhvcNAQELBQAw
|
|
||||||
JjERMA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE4MDUy
|
|
||||||
MTIyNTcyN1oXDTI4MDgyNjIyNTcyN1owJzERMA8GA1UEChMIUXVpY2tUTFMxEjAQ
|
|
||||||
BgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
|
||||||
ANr32CUXFUCW1c2oPoHjq76T8jUTH/cxPiR5NabJ1y4gMCBko2rIe+TblW9UclxH
|
|
||||||
911gjfpSAxFtNf+lX5kwmAMHhU8pcCc+Mjp3Ax9acFXSXvzzTDg+xj0NGig6OBk3
|
|
||||||
jyPuO92lM8A4qs0mBZ/T04iLkawLmdRXViRoGK/T7Df8HN+hm7UsG0VO3GxFgSST
|
|
||||||
YhhKTu6JMTADszbIFPOvBxGCUNhffXiLNyviO4AiBdcAv2v0SUadEPmSGm5Jb1DK
|
|
||||||
tfKY0jWi1k1zNSqzit/bhML/EHbVkYJ00QmH50MBTunpz60gIgHjt48nzJarLDML
|
|
||||||
oRFMppG9XIBQlUn3lo0gVwcCAwEAAaM2MDQwDgYDVR0PAQH/BAQDAgWgMAwGA1Ud
|
|
||||||
EwEB/wQCMAAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IB
|
|
||||||
AQAb388owui+O9vUle+A99FXwcMDEb0OILc0lBXVWx8q5ZE73vcanxyAcfOsZYRY
|
|
||||||
Lh7G6VtJwC9xVjAdNwJ1gd+ak1l0/Rhs1V0JZ12/wOvAOQ7+9g2lRc1IedOh3EIh
|
|
||||||
d3BMI4RdDB/BnnK3XjkggYQZK3yiAOavmmsZxAOl/apzjF+5u8XjuydMmotE2NYw
|
|
||||||
IpM93zE5wWXqzYs/Kmyy7zAcHKfvq9xej/gMCFEvO6lopmwyslBLPpPNHwyfIVtA
|
|
||||||
mspm2OZhdmpRJYGzkR4wK5NjoRl2O11uzlMRDckp0GSZ0x6TGxmb7ot5HK27p3ep
|
|
||||||
6LPZM1wJIwuYHIP74eH0ctQP
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpQIBAAKCAQEA2vfYJRcVQJbVzag+geOrvpPyNRMf9zE+JHk1psnXLiAwIGSj
|
|
||||||
ash75NuVb1RyXEf3XWCN+lIDEW01/6VfmTCYAweFTylwJz4yOncDH1pwVdJe/PNM
|
|
||||||
OD7GPQ0aKDo4GTePI+473aUzwDiqzSYFn9PTiIuRrAuZ1FdWJGgYr9PsN/wc36Gb
|
|
||||||
tSwbRU7cbEWBJJNiGEpO7okxMAOzNsgU868HEYJQ2F99eIs3K+I7gCIF1wC/a/RJ
|
|
||||||
Rp0Q+ZIabklvUMq18pjSNaLWTXM1KrOK39uEwv8QdtWRgnTRCYfnQwFO6enPrSAi
|
|
||||||
AeO3jyfMlqssMwuhEUymkb1cgFCVSfeWjSBXBwIDAQABAoIBAGQMCf4oZdV1FYs5
|
|
||||||
7BV86OPSxT/q1Rgkr7gKibEDWAYDPvoOAXywzarriYOsmfQADc3kZ/qPrkcwFxQP
|
|
||||||
g3aC9XGs5gQdctj7WgfMiOiycdFEpZH9uD2asQkEC4eF0kvzTrukBkZnTRXuzlud
|
|
||||||
m8RDDMu+uXhadJbIsNtBlMYBllSdS+LFxXcAYm+IsvTYzmwg4+bnjvOwMHO9SMSb
|
|
||||||
1dfgOLkg/A++/GTjD/kUyCV5dc4lv2I0i2pXJkD2V0Dr6Yra1U/MRKcOwTGC2q/8
|
|
||||||
hZuKm9DgvGXvZsG0+yT5fsexGRwTxmByvfj+QMF3LCTDCknD4d/mmEEX0EEGPlW2
|
|
||||||
I7OgKEECgYEA/LkdwnXy7ymis1Rgjumc3ydcLoCqV3ExaxXrvO50EkRpgRX/TLEk
|
|
||||||
j98iVYyksiaJuMhqnxNttT6GwWJvwIXFPP9WpIGmzi4GKyqYGEX4WbyPoY9hjt/G
|
|
||||||
muR67cTXg6ssiSssUCoQnWIHyuGDJfzRWqnoei0dIA2GobOwFJtXeV0CgYEA3c6u
|
|
||||||
utbNtmbyp17Jffx01ee8Wprhnoz7Nh/dJMLngpIx3i8qQqpFB8TPNUTu+GLgGcol
|
|
||||||
n9BDzZszoVhsxybn7Lgm/OjS/jQL4hosFoqztThkg28L8UD7QB0TyCucwgk2lgOe
|
|
||||||
VxyX25kNSXzxdCYaKr1+6g2gtBAb0zPj2E+5t7MCgYEAimoA6J6dHWwaVkmiUOOW
|
|
||||||
LYprLHT/1sCCJnptEJ8xJ0gc2LxphWGH+txk+6H6GjCNQY1TCCkl7xx9xbDaMAGU
|
|
||||||
E2Jt28++wjHm4wGDJ9g6uztRF1VmQ1BAgFkfEta6irzXuZDRxl4jl283gWCd6dJb
|
|
||||||
/2ILl87ZotKFqE6347Fo6WkCgYEAyDNyMMALIzTelkUO1wFUL3If5yPeuy4C3IJ8
|
|
||||||
J18oeQkdq66klVF8RxvT7v/ONjGAlqaHuSzQ1jbcrifS3xp1wYsh3asELl+pziXT
|
|
||||||
X3FH7Sz+REep3tLJNMBKB6WdsuF//H09oOD1DEej342/nhd6DNPHRtiQEZZslwBC
|
|
||||||
Cg9D0NMCgYEArNksPSQJSxXqxZsw17OTqQJnf3kNBI0SP9q6Wc8gN69r5YQcIHcr
|
|
||||||
KgtfdiL4LawZFie6gcNu398ng7VYUzzkYR9j+G5qPetcqllQZeVc6cieUyR7Eul0
|
|
||||||
WvtlUECCfweLFUsIhuHyEsGu1PrFYd98SlOzt24utguFss1539cEC3A=
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDFTCCAf2gAwIBAgIQTyBNJlm7fS0yutwdLbhG9zANBgkqhkiG9w0BAQsFADAm
|
|
||||||
MREwDwYDVQQKEwhRdWlja1RMUzERMA8GA1UEAxMIUXVpY2tUTFMwHhcNMTgwNTIx
|
|
||||||
MjI1NzI4WhcNMjgwODI2MjI1NzI4WjArMREwDwYDVQQKEwhRdWlja1RMUzEWMBQG
|
|
||||||
A1UEAxMNbG9jYWxyZWdpc3RyeTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
|
||||||
ggEBANSMT7auGdwF63fFdQM9O/EqrX++gnuBQgFa4cZzC7GqsvS90uKTOLuWIA2U
|
|
||||||
ehgF548EDkZu1z6nRAvoFh5L6B5f1VjiVknzLEPlR+5uPD22kbcxgCrMCRZn+5mK
|
|
||||||
vJhTUpx18yeBXMhxtPhkGnKaKwGcgeW8O69KM7Mo4HBQqg5656pa+4wkUo7GX2v0
|
|
||||||
R4ZqmrS1tlwOgpld8KZKVJ1FNyGEeKQkIYGJKHqgC2/JrXsbzuSZ/4pqf8BHc6Mb
|
|
||||||
AHU85RlBFVDHFPMtQ7Rg1vrhYzgInKeqXtc2kEAe63nqyYyHxPOUd3vIQX/N4tdB
|
|
||||||
aH41ffs68Pdtp9GeocTiYyj7KuUCAwEAAaM6MDgwDgYDVR0PAQH/BAQDAgWgMAwG
|
|
||||||
A1UdEwEB/wQCMAAwGAYDVR0RBBEwD4INbG9jYWxyZWdpc3RyeTANBgkqhkiG9w0B
|
|
||||||
AQsFAAOCAQEAkjfZvcd5WysbfqGfhPErG7ADWAFJ1bsIDlHVUaEn2/Asr68iJpfF
|
|
||||||
fqb0fhBkBExPhiLDS+jmL1L86QRNIgyM+7zGCCagKJkl9uNBGXPdS6KxZtY8W8rV
|
|
||||||
bF/GIYnYUL5pnyrhX4pH2ZnDJpKIAJl8CAZ1VHwErQ5VqnJAX/gGO/eKgiyCciZv
|
|
||||||
WmmQkhcOo60FwLW+Wi9sLOYD+YAT+VnFrGfak/SDfT78wrmmfg5v05tvFXgJaZLh
|
|
||||||
JSxRET9D5iT3DIxb+m5GyQAqIH1djh02ybrPJ9j6/+qRQDojIe5qJUL90qIvhwO+
|
|
||||||
aSbIL/p+I6//AUMWJvcR7GbXy3xywgmaYw==
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpAIBAAKCAQEA1IxPtq4Z3AXrd8V1Az078Sqtf76Ce4FCAVrhxnMLsaqy9L3S
|
|
||||||
4pM4u5YgDZR6GAXnjwQORm7XPqdEC+gWHkvoHl/VWOJWSfMsQ+VH7m48PbaRtzGA
|
|
||||||
KswJFmf7mYq8mFNSnHXzJ4FcyHG0+GQacporAZyB5bw7r0ozsyjgcFCqDnrnqlr7
|
|
||||||
jCRSjsZfa/RHhmqatLW2XA6CmV3wpkpUnUU3IYR4pCQhgYkoeqALb8mtexvO5Jn/
|
|
||||||
imp/wEdzoxsAdTzlGUEVUMcU8y1DtGDW+uFjOAicp6pe1zaQQB7reerJjIfE85R3
|
|
||||||
e8hBf83i10FofjV9+zrw922n0Z6hxOJjKPsq5QIDAQABAoIBAQCLj3Xn5XllVx29
|
|
||||||
jxG+Br8NI5C4iEb1AXJtoVcODwxmpEbNHLcTvsdJpNF3GT7x9y6MYYVeCfmbUgkE
|
|
||||||
KGgdjInlJ9fWfQdblyhBjJMmo4s6ml4jg4U8lKyC4dP6hXZALrXXtjrqfa6GjuLd
|
|
||||||
Fh2nkkMa08EXL/mgp4A662QzW0POLQIo1lMJc49FFPrVQneLedUdsJDowNz/HU/q
|
|
||||||
oD4/SsKw6inUh/A1MfSKvEhnJcVH4fiQhFQU5CdSzAHPmAYcoBeg6LjY+WScJAAs
|
|
||||||
Hu5kgunbCsB5vw9WbFDQzM1HYtW1CvJj1cjNp662b06D7VQugjtawhHNImkq1/65
|
|
||||||
H2ZTglchAoGBAPu0OX3tEvtic4f8VLRv/TeI9NSC3EgRAtIDncDo+nwVjR54AXID
|
|
||||||
aePceImGUsDd5xfLuQTiYp50z0cEB5CGsWYbnjm0hliF8YXz/tpqi0V0Cr8fLLA8
|
|
||||||
/jG3tajbZ8xu/3p1iEcIPevYT/44bjbOyDp5peQIHhr32LZ1gZfQDRt7AoGBANgt
|
|
||||||
AIid1rPIyEzhhznpWVjw/ZIrtgaP0HDgKaUUCsEqEDoOJEaFS7WG4G7m8/iS4f8v
|
|
||||||
XGgcoYf4TjfIwYtRQy2Bp9g4oOMiUbQKukF1DuFJpsw69y3hNNoZoUm7r2jpv3Q8
|
|
||||||
/NY+O+BNaTVdmbOjNHmKo99MYGh1cPUPVGxuP1UfAoGBAOJ9fe5OUfJa2NLYv+/N
|
|
||||||
hfFfD8/aIRXIGN2Z224nNp5JVj7AhaxuXe5oCR7W+8gI5VWIP+ihPVSQj6O7gIMQ
|
|
||||||
cLkMyQfr5afqfzamJAGuNbw9ex4Xk0LS33klchWLuI9Aoiszb3lbdTyv3OtJJAO1
|
|
||||||
dn8Hz7qtg0mJFDy65+4PjHvZAoGAXtKmmEZ75hKdYbPPiCSGT5At+g74Yjp1GP4K
|
|
||||||
5mE7Mm3L/lszqEdR5UdLbPobbB6pyTCyHOzqIeVWEfwagYzcpbposFxunhLwucO2
|
|
||||||
3X2GUGXpJ056HALcFwsFB32vPJrDoy4ZTbSwuPvbuU/cWsKtAt9AcHNlGozhRm05
|
|
||||||
//IAD8sCgYAUs6ibNtUqCFjekr10FBGFuA2ZQg+9bQYw3ti+S6uFMsxIDqYRC2bG
|
|
||||||
yvKhEYym/W7RwfzPWjGzuvFbZWzJnnb81WLfcI4DnrJe3h8THlnaBQhcsEObu84O
|
|
||||||
XS/sYeVo5c6l0kTNp0I8vXbn05bExZlsLAIICMTsm5bSQZI/iCRyEw==
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1 +0,0 @@
|
||||||
testuser:$apr1$YmLhHjm6$AjP4z8J1WgcUNxU8J4ue5.
|
|
|
@ -1 +0,0 @@
|
||||||
{"num_pages":1,"num_results":2,"page":1,"page_size": 25,"query":"testsearch","results":[{"description":"","is_automated":false,"is_official":false,"is_trusted":false, "name":"dmcgowan/testsearch-1","star_count":1000},{"description":"Some automated build","is_automated":true,"is_official":false,"is_trusted":false,"name":"dmcgowan/testsearch-2","star_count":10}]}
|
|
|
@ -1,103 +0,0 @@
|
||||||
#!/usr/bin/env bats
|
|
||||||
|
|
||||||
# This tests pushing and pulling plugins
|
|
||||||
|
|
||||||
load helpers
|
|
||||||
|
|
||||||
user="testuser"
|
|
||||||
password="testpassword"
|
|
||||||
base="hello-world"
|
|
||||||
|
|
||||||
#TODO: Create plugin image
|
|
||||||
function create_plugin() {
|
|
||||||
plugindir=$(mktemp -d)
|
|
||||||
|
|
||||||
cat - > $plugindir/config.json <<CONFIGJSON
|
|
||||||
{
|
|
||||||
"manifestVersion": "v0",
|
|
||||||
"description": "A test plugin for integration tests",
|
|
||||||
"entrypoint": ["/usr/bin/ncat", "-l", "-U", "//run/docker/plugins/plugin.sock"],
|
|
||||||
"interface" : {
|
|
||||||
"types": ["docker.volumedriver/1.0"],
|
|
||||||
"socket": "plugin.sock"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CONFIGJSON
|
|
||||||
|
|
||||||
cid=$(docker create dmcgowan/ncat:latest /bin/sh)
|
|
||||||
|
|
||||||
mkdir $plugindir/rootfs
|
|
||||||
|
|
||||||
docker export $cid | tar -x -C $plugindir/rootfs
|
|
||||||
|
|
||||||
docker rm $cid
|
|
||||||
|
|
||||||
daemontmp=$(docker exec dockerdaemon mktemp -d)
|
|
||||||
|
|
||||||
tar -c -C $plugindir . | docker exec -i dockerdaemon tar -x -C $daemontmp
|
|
||||||
|
|
||||||
docker exec dockerdaemon docker plugin create $1 $daemontmp
|
|
||||||
|
|
||||||
docker exec dockerdaemon rm -rf $daemontmp
|
|
||||||
|
|
||||||
rm -rf $plugindir
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test plugin push and pull" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.13.0-rc3"
|
|
||||||
version_check docker "$GOLEM_DISTRIBUTION_VERSION" "2.6.0"
|
|
||||||
|
|
||||||
login_oauth localregistry:5558
|
|
||||||
image="localregistry:5558/testuser/plugin1"
|
|
||||||
|
|
||||||
create_plugin $image
|
|
||||||
|
|
||||||
run docker_t plugin push $image
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
docker_t plugin rm $image
|
|
||||||
|
|
||||||
docker_t plugin install --grant-all-permissions $image
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test plugin push and failed image pull" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.13.0-rc3"
|
|
||||||
version_check docker "$GOLEM_DISTRIBUTION_VERSION" "2.6.0"
|
|
||||||
|
|
||||||
|
|
||||||
login_oauth localregistry:5558
|
|
||||||
image="localregistry:5558/testuser/plugin-not-image"
|
|
||||||
|
|
||||||
create_plugin $image
|
|
||||||
|
|
||||||
run docker_t plugin push $image
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
docker_t plugin rm $image
|
|
||||||
|
|
||||||
run docker_t pull $image
|
|
||||||
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test image push and failed plugin pull" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.13.0-rc3"
|
|
||||||
version_check docker "$GOLEM_DISTRIBUTION_VERSION" "2.6.0"
|
|
||||||
|
|
||||||
login_oauth localregistry:5558
|
|
||||||
image="localregistry:5558/testuser/image-not-plugin"
|
|
||||||
|
|
||||||
build $image "$base:latest"
|
|
||||||
|
|
||||||
run docker_t push $image
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
docker_t rmi $image
|
|
||||||
|
|
||||||
run docker_t plugin install --grant-all-permissions $image
|
|
||||||
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Run the integration tests with multiple versions of the Docker engine
|
|
||||||
|
|
||||||
set -e
|
|
||||||
set -x
|
|
||||||
|
|
||||||
DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
||||||
|
|
||||||
|
|
||||||
if [ "$TMPDIR" != "" ] && [ ! -d "$TMPDIR" ]; then
|
|
||||||
mkdir -p $TMPDIR
|
|
||||||
fi
|
|
||||||
|
|
||||||
cachedir=`mktemp -t -d golem-cache.XXXXXX`
|
|
||||||
trap "rm -rf $cachedir" EXIT
|
|
||||||
|
|
||||||
if [ "$1" == "-d" ]; then
|
|
||||||
# Drivers to use for Docker engines the tests are going to create.
|
|
||||||
STORAGE_DRIVER=${STORAGE_DRIVER:-overlay}
|
|
||||||
|
|
||||||
docker daemon --log-level=panic --storage-driver="$STORAGE_DRIVER" &
|
|
||||||
DOCKER_PID=$!
|
|
||||||
|
|
||||||
# Wait for it to become reachable.
|
|
||||||
tries=10
|
|
||||||
until docker version &> /dev/null; do
|
|
||||||
(( tries-- ))
|
|
||||||
if [ $tries -le 0 ]; then
|
|
||||||
echo >&2 "error: daemon failed to start"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
trap "kill $DOCKER_PID" EXIT
|
|
||||||
fi
|
|
||||||
|
|
||||||
distimage=$(docker build -q $DIR/../..)
|
|
||||||
fullversion=$(git describe --match 'v[0-9]*' --dirty='.m' --always)
|
|
||||||
distversion=${fullversion:1}
|
|
||||||
|
|
||||||
echo "Testing image $distimage with distribution version $distversion"
|
|
||||||
|
|
||||||
# Pull needed images before invoking golem to get pull time
|
|
||||||
# These images are defined in golem.conf
|
|
||||||
time docker pull nginx:1.9
|
|
||||||
time docker pull golang:1.6
|
|
||||||
time docker pull dmcgowan/token-server:simple
|
|
||||||
time docker pull dmcgowan/token-server:oauth
|
|
||||||
time docker pull distribution/golem-runner:0.1-bats
|
|
||||||
|
|
||||||
time docker pull docker:1.9.1-dind
|
|
||||||
time docker pull docker:1.10.3-dind
|
|
||||||
time docker pull docker:1.11.1-dind
|
|
||||||
time docker pull docker:1.12.3-dind
|
|
||||||
time docker pull docker:1.13.0-rc5-dind
|
|
||||||
|
|
||||||
golem -cache $cachedir \
|
|
||||||
-i "golem-distribution:latest,$distimage,$distversion" \
|
|
||||||
-i "golem-dind:latest,docker:1.9.1-dind,1.9.1" \
|
|
||||||
-i "golem-dind:latest,docker:1.10.3-dind,1.10.3" \
|
|
||||||
-i "golem-dind:latest,docker:1.11.1-dind,1.11.1" \
|
|
||||||
-i "golem-dind:latest,docker:1.12.3-dind,1.12.3" \
|
|
||||||
-i "golem-dind:latest,docker:1.13.0-rc5-dind,1.13.0" \
|
|
||||||
$DIR
|
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
#!/usr/bin/env bats
|
|
||||||
|
|
||||||
# Registry host name, should be set to non-localhost address and match
|
|
||||||
# DNS name in nginx/ssl certificates and what is installed in /etc/docker/cert.d
|
|
||||||
|
|
||||||
load helpers
|
|
||||||
|
|
||||||
hostname="localregistry"
|
|
||||||
base="hello-world"
|
|
||||||
image="${base}:latest"
|
|
||||||
|
|
||||||
# Login information, should match values in nginx/test.passwd
|
|
||||||
user=${TEST_USER:-"testuser"}
|
|
||||||
password=${TEST_PASSWORD:-"passpassword"}
|
|
||||||
|
|
||||||
function setup() {
|
|
||||||
tempImage $image
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test valid certificates" {
|
|
||||||
docker_t tag $image $hostname:5440/$image
|
|
||||||
run docker_t push $hostname:5440/$image
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test basic auth" {
|
|
||||||
basic_auth_version_check
|
|
||||||
login $hostname:5441
|
|
||||||
docker_t tag $image $hostname:5441/$image
|
|
||||||
run docker_t push $hostname:5441/$image
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test basic auth with build" {
|
|
||||||
basic_auth_version_check
|
|
||||||
login $hostname:5441
|
|
||||||
|
|
||||||
image1=$hostname:5441/$image-build
|
|
||||||
image2=$hostname:5441/$image-build-2
|
|
||||||
|
|
||||||
tempImage $image1
|
|
||||||
|
|
||||||
run docker_t push $image1
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
docker_t rmi $image1
|
|
||||||
|
|
||||||
run build $image2 $image1
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
run docker_t push $image2
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test TLS client auth" {
|
|
||||||
docker_t tag $image $hostname:5442/$image
|
|
||||||
run docker_t push $hostname:5442/$image
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test TLS client with invalid certificate authority fails" {
|
|
||||||
docker_t tag $image $hostname:5443/$image
|
|
||||||
run docker_t push $hostname:5443/$image
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test basic auth with TLS client auth" {
|
|
||||||
basic_auth_version_check
|
|
||||||
login $hostname:5444
|
|
||||||
docker_t tag $image $hostname:5444/$image
|
|
||||||
run docker_t push $hostname:5444/$image
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test unknown certificate authority fails" {
|
|
||||||
docker_t tag $image $hostname:5445/$image
|
|
||||||
run docker_t push $hostname:5445/$image
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test basic auth with unknown certificate authority fails" {
|
|
||||||
run login $hostname:5446
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
docker_t tag $image $hostname:5446/$image
|
|
||||||
run docker_t push $hostname:5446/$image
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test TLS client auth to server with unknown certificate authority fails" {
|
|
||||||
docker_t tag $image $hostname:5447/$image
|
|
||||||
run docker_t push $hostname:5447/$image
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test failure to connect to server fails to fallback to SSLv3" {
|
|
||||||
docker_t tag $image $hostname:5448/$image
|
|
||||||
run docker_t push $hostname:5448/$image
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
#!/usr/bin/env bats
|
|
||||||
|
|
||||||
# This tests contacting a registry using a token server
|
|
||||||
|
|
||||||
load helpers
|
|
||||||
|
|
||||||
user="testuser"
|
|
||||||
password="testpassword"
|
|
||||||
base="hello-world"
|
|
||||||
|
|
||||||
@test "Test token server login" {
|
|
||||||
login localregistry:5554
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test token server bad login" {
|
|
||||||
docker_t_login -u "testuser" -p "badpassword" localregistry:5554
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
|
|
||||||
docker_t_login -u "baduser" -p "testpassword" localregistry:5554
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test push and pull with token auth" {
|
|
||||||
login localregistry:5555
|
|
||||||
image="localregistry:5555/testuser/token"
|
|
||||||
build $image "$base:latest"
|
|
||||||
|
|
||||||
run docker_t push $image
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
docker_t rmi $image
|
|
||||||
|
|
||||||
docker_t pull $image
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test push and pull with token auth wrong namespace" {
|
|
||||||
login localregistry:5555
|
|
||||||
image="localregistry:5555/notuser/token"
|
|
||||||
build $image "$base:latest"
|
|
||||||
|
|
||||||
run docker_t push $image
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test oauth token server login" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.11.0"
|
|
||||||
|
|
||||||
login_oauth localregistry:5557
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test oauth token server bad login" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.11.0"
|
|
||||||
|
|
||||||
docker_t_login -u "testuser" -p "badpassword" -e $email localregistry:5557
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
|
|
||||||
docker_t_login -u "baduser" -p "testpassword" -e $email localregistry:5557
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test oauth push and pull with token auth" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.11.0"
|
|
||||||
|
|
||||||
login_oauth localregistry:5558
|
|
||||||
image="localregistry:5558/testuser/token"
|
|
||||||
build $image "$base:latest"
|
|
||||||
|
|
||||||
run docker_t push $image
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
docker_t rmi $image
|
|
||||||
|
|
||||||
docker_t pull $image
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test oauth push and build with token auth" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.11.0"
|
|
||||||
|
|
||||||
login_oauth localregistry:5558
|
|
||||||
image="localregistry:5558/testuser/token-build"
|
|
||||||
tempImage $image
|
|
||||||
|
|
||||||
run docker_t push $image
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
docker_t rmi $image
|
|
||||||
|
|
||||||
image2="localregistry:5558/testuser/token-build-2"
|
|
||||||
run build $image2 $image
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
run docker_t push $image2
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
has_digest "$output"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test oauth push and pull with token auth wrong namespace" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.11.0"
|
|
||||||
|
|
||||||
login_oauth localregistry:5558
|
|
||||||
image="localregistry:5558/notuser/token"
|
|
||||||
build $image "$base:latest"
|
|
||||||
|
|
||||||
run docker_t push $image
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "Test oauth with v1 search" {
|
|
||||||
version_check docker "$GOLEM_DIND_VERSION" "1.12.0"
|
|
||||||
|
|
||||||
run docker_t search localregistry:5600/testsearch
|
|
||||||
[ "$status" -ne 0 ]
|
|
||||||
|
|
||||||
login_oauth localregistry:5600
|
|
||||||
|
|
||||||
run docker_t search localregistry:5600/testsearch
|
|
||||||
echo $output
|
|
||||||
[ "$status" -eq 0 ]
|
|
||||||
|
|
||||||
echo $output | grep "testsearch-1"
|
|
||||||
echo $output | grep "testsearch-2"
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
testuser:$2y$05$T2MlBvkN1R/yICNnLuf1leOlOfAY0DvybctbbWUFKlojfkShVgn4m
|
|
|
@ -1,8 +0,0 @@
|
||||||
FROM dmcgowan/token-server@sha256:5a6f76d3086cdf63249c77b521108387b49d85a30c5e1c4fe82fdf5ae3b76ba7
|
|
||||||
|
|
||||||
WORKDIR /
|
|
||||||
|
|
||||||
COPY ./.htpasswd /.htpasswd
|
|
||||||
COPY ./certs/auth.localregistry.cert /tls.cert
|
|
||||||
COPY ./certs/auth.localregistry.key /tls.key
|
|
||||||
COPY ./certs/signing.key /sign.key
|
|
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDHDCCAgagAwIBAgIRAKhhQMnqZx+hkOmoUYgPb+kwCwYJKoZIhvcNAQELMCYx
|
|
||||||
ETAPBgNVBAoTCFF1aWNrVExTMREwDwYDVQQDEwhRdWlja1RMUzAeFw0xNjAxMjgw
|
|
||||||
MDQyMzFaFw0xOTAxMTIwMDQyMzFaMDAxETAPBgNVBAoTCFF1aWNrVExTMRswGQYD
|
|
||||||
VQQDExJhdXRoLmxvY2FscmVnaXN0cnkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
|
||||||
ggEKAoIBAQD1tUf1EghBlIRrE83yF4zDgRu7vH2Jo0kygKJUWtQQe+DfXyjjE/fg
|
|
||||||
FdKnnoEjsIeF9hxNbTt0ldDz7/n97pbMhoiXULi9iq4jlgSzVL2XEAgrON0YSY/c
|
|
||||||
Lmmd1KSa/pOUZr2WMAYPZ+FdQfE1W7SMNbErPefBqYdFzpZ+esAtvbajYwIjl8Vy
|
|
||||||
9c4bidx4vgnNrR9GcFYibjC5sj8syh/OtbzzqiVGT8YcPpmMG6KNRkausa4gqpon
|
|
||||||
NKYG8C3WDaiPCLYKcvFrFfdEWF/m2oj14eXACXT9iwp8r4bsLgXrZwqcpKOWfVRu
|
|
||||||
qHC8aV476EYgxWCAOANExUdUaRt5wL/jAgMBAAGjPzA9MA4GA1UdDwEB/wQEAwIA
|
|
||||||
oDAMBgNVHRMBAf8EAjAAMB0GA1UdEQQWMBSCEmF1dGgubG9jYWxyZWdpc3RyeTAL
|
|
||||||
BgkqhkiG9w0BAQsDggEBABxPGK9FdGDxcLowNsExKnnZvmQT3H0u+Dux1gkp0AhH
|
|
||||||
KOrmx3LUENUKLSgotzx133tgOgR5lzAWVFy7bhLwlPhOslxf2oEfztsAMd/tY8rW
|
|
||||||
PrG2ZqYqlzEQQ9INbAc3woo5A3slN07uhP3F16jNqoMM4zRmw6Ba70CluGKT7x5+
|
|
||||||
xVjKoWITLjWDXT5m35PnsN8CpBaFzXYcod/5p9XwCFp0s+aNxfpZECCV/3yqIr+J
|
|
||||||
ALzroPh43FAlG96o4NyYZ2Msp63newN19R2+TgpV4nXuw2mLVDpvetP7RRqnpvj/
|
|
||||||
qwRgt5j4hFjJWb61M0ELL7A9fA71h1ImdGCvnArdBQs=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpAIBAAKCAQEA9bVH9RIIQZSEaxPN8heMw4Ebu7x9iaNJMoCiVFrUEHvg318o
|
|
||||||
4xP34BXSp56BI7CHhfYcTW07dJXQ8+/5/e6WzIaIl1C4vYquI5YEs1S9lxAIKzjd
|
|
||||||
GEmP3C5pndSkmv6TlGa9ljAGD2fhXUHxNVu0jDWxKz3nwamHRc6WfnrALb22o2MC
|
|
||||||
I5fFcvXOG4nceL4Jza0fRnBWIm4wubI/LMofzrW886olRk/GHD6ZjBuijUZGrrGu
|
|
||||||
IKqaJzSmBvAt1g2ojwi2CnLxaxX3RFhf5tqI9eHlwAl0/YsKfK+G7C4F62cKnKSj
|
|
||||||
ln1UbqhwvGleO+hGIMVggDgDRMVHVGkbecC/4wIDAQABAoIBAQCrsjXKRwOF8CZo
|
|
||||||
PLqZBWPT6hBbK+f9miC4LbNBhwbRTf9hl7mWlImOCTHe95/+NIk/Ty+P21jEqzwM
|
|
||||||
ehETJPoziX9BXaL6sEHnlBlMx1aEjStoKKA3LJBeqAAdzk4IEQVHmlO4824IreqJ
|
|
||||||
pF7Njnunzo0zTlr4tWJVoXsAfv5z9tNtdkxYBbIa0fjfGtlqXU3gLq58FCON3mB/
|
|
||||||
NGc0AyA1UFGp0FzpdEcwTGD4InsXbcmsl2l/VPBJuZbryITRqWs6BbK++80DRhNt
|
|
||||||
afMhP+IzKrWSCp0rBYrqqz6AevtlKdEfQK1yXPEjN/63QLMevt8mF/1JCp//TQnf
|
|
||||||
Z6bIQbAhAoGBAP7vFA0PcvoXt9MXvvAwrKY1s6pNw4nWPG27qY1/m+DkBwP8IQms
|
|
||||||
4AWGv1wscZzXJYTvaLO5/qjmGUj50ohcVEvyZJioh1pKXA8Chxvd6rBA/O/Lj5E0
|
|
||||||
3MOSA5Q0gxJ0Mhv0zGbbyN5fY8D8zhxoqQP4LoW+UdZG2Oi6JxsQ9c9dAoGBAPa8
|
|
||||||
U3bGuM5OGA9EWP7mkB/VnjDTL1aEIN3cOHbHIKwH/loxdYcNMBE7vwxV1CzgIzXT
|
|
||||||
wsL0iE15fQdK938u0+um8aH5QtbWNI8tdk1XVjEC/i3C7N6WVUutneCKUDb4QxiB
|
|
||||||
9OvWCbNNiN+xTKBBM93YlwO3GYfrW9Pmm9q1+hg/AoGBALJlUS22gun50PxaIJZq
|
|
||||||
KVcCO2DQnCYHki/j48mN4+HjD/m85M2lePrFCYIR48syTyIQer9SR5+frVAA6k/b
|
|
||||||
9G1VCQo+3MDVSkiCp1Nb3tBKGfYgB65ARMBinDiI6rPuNeaUTrkn0g+yxtaU0hLV
|
|
||||||
Nnj9omia/x+oYj+xjI4HN0xNAoGARy92dSJIV104m88ATip/EnAzP6ruUWu1f8z1
|
|
||||||
jW9OAdQckjEK03f+kjpGmGx61qekAPejjVO3r4KJi/0ZAtyjz61OsYiUvB748wYO
|
|
||||||
x6mW+HUAmHtQk7eTzE2+6vV8xx9BXGTCIPiTu+N2xfMFRIcLS8odZ7j/6LMCv1Qd
|
|
||||||
SzCNg0kCgYBaNlEs4pK1VxZZpEWwVmFpgIxfEfxLIaGrek6wBTcCn/VA2M0oHuez
|
|
||||||
mlMio8VY0yWPBJz30JflDiTmYIvteLPMHT0N0J6isiXLhzJSFI4+cAMLE2Q5v8rz
|
|
||||||
W+W5/L8YZeierW0qJat1BrgStaf5ZLpiOc9pKBSwycydPH5BfVdK/A==
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,18 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIC9TCCAd+gAwIBAgIQNS9SaFSFBN7Zvwjalrf2DDALBgkqhkiG9w0BAQswJjER
|
|
||||||
MA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE2MDEyODAw
|
|
||||||
NDIzMFoXDTE5MDExMjAwNDIzMFowJjERMA8GA1UEChMIUXVpY2tUTFMxETAPBgNV
|
|
||||||
BAMTCFF1aWNrVExTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu/Pf
|
|
||||||
fQ7VUTSXs12PRyrLDVDz7kPDbGNTt0vF7FYDmTTGOU3i62xZNOGuxBezAiVSV5A3
|
|
||||||
lopwsv4OH7DRtSaPn+XCt1JDALna2WrjT0MshypMd5o2c3jmGUfAKf5gjizgIoEl
|
|
||||||
d4e5aqEBuOQP+QCEde+8p8N1buQW+zMy9srM2O/7BFMIaQ07CWLlj3hIiF+L5rKD
|
|
||||||
L6dWtKT7INRmRwpuZZnThEWnBSNgayrWek6G0i3y8QYTfVA1SwA+H3grJxy5NrLp
|
|
||||||
GYXSmu2509mu0QAHhx05t1rJhwhFz/4sG7j8AggYeDXEqfQ/VIb/bvnW9bD+vrQ2
|
|
||||||
ZnICvxnzNMYBx23BkQIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAKQwDwYDVR0TAQH/
|
|
||||||
BAUwAwEB/zALBgkqhkiG9w0BAQsDggEBALvTi6E44Fltu83dFLVEj0kLtusI/TTH
|
|
||||||
Tw6upoB5pRG+7A75w0Ii8bvvd2tNpBOg+L+80xyIFqaNkXhLKTN4lgtd7WiCuyb/
|
|
||||||
w1BEuF/+RjCXhu6wQ/63ab46d6ctaQ1zjxlU2rQLQXQFALI8ntyn/TELc01HYkr2
|
|
||||||
x3NHlbnBNlgI2CKXPeUBzvBylTCcdYGwoa+2ZPdIsFjle2aCIBoZ+WNZlIbFwgLh
|
|
||||||
XCHwcbviC+thjqOneJpJZmRW9AxQ638ki6iGItdrJewCN/1dcL2KKjxnC5VHbpne
|
|
||||||
SOjEPNXihY08Brl8myhFNtRRKZ55MJIYzDtVQSkCaT91Q3XX9tSZadY=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDETCCAfugAwIBAgIQN7rT95eAy75c4n6/AsDJODALBgkqhkiG9w0BAQswJjER
|
|
||||||
MA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE2MDEyODAw
|
|
||||||
NDIzMloXDTE5MDExMjAwNDIzMlowKzERMA8GA1UEChMIUXVpY2tUTFMxFjAUBgNV
|
|
||||||
BAMTDWxvY2FscmVnaXN0cnkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
|
||||||
AQDLi75QEkl/qekcoOJlNv9y1IXvrbU2ssl4ViJiZRjWx+/CkyCCOyf9YUpAgRLr
|
|
||||||
Pskqde2mwhuNP8yBlOBb17Sapz7N3+hJi5j9vLBAFcamPeF3PqxjFv7j5TKkRmSI
|
|
||||||
dFYQclREwMUd3qEH322KkqOnsEEfdmCgFqWORe+QR5AxzxQP3Pnd4OYH1yZCh0MQ
|
|
||||||
P2pJgrxxf2I5I/m1AUgoHV1cdBbCv9LGohJPpMtwPC0dJpgMFcnf6hT37At236AY
|
|
||||||
V437HiRruY7iPWkYFrSPWpwdslJ32MZvRN5RS163jZXjiZ7qWnQOiiDJfXe4evB/
|
|
||||||
yQLN4m0qVQxsMz7rkY7OsqaXAgMBAAGjOjA4MA4GA1UdDwEB/wQEAwIAoDAMBgNV
|
|
||||||
HRMBAf8EAjAAMBgGA1UdEQQRMA+CDWxvY2FscmVnaXN0cnkwCwYJKoZIhvcNAQEL
|
|
||||||
A4IBAQAyUb3EuMaOylBeV8+4KeBiE4lxykDOwLLSk3jXRsVVtfJpX3v8l5vwo/Jf
|
|
||||||
iG8tzzz+7uiskI96u3TsekUtVkUxujfKevMP+369K/59s7NRmwwlFMyB2fvL14B2
|
|
||||||
oweVjWvM/8fZl6irtFdbJFXXRm7paKso5cmfImxhojAwohgcd4XTVLE/7juYa582
|
|
||||||
AaBdRuIiyL71MU9qa1mC5+57AaSLPYaPKpahemgYYkV1Z403Kd6rXchxdQ8JIAL8
|
|
||||||
+0oYTSC+svnz1tUU/V5E5id9LQaTmDN5iIVFhNpqAaZmR45UI86woWvnkMb8Ants
|
|
||||||
4aknwTwY3300PuTqBdQufvOFDRN5
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpAIBAAKCAQEAy4u+UBJJf6npHKDiZTb/ctSF7621NrLJeFYiYmUY1sfvwpMg
|
|
||||||
gjsn/WFKQIES6z7JKnXtpsIbjT/MgZTgW9e0mqc+zd/oSYuY/bywQBXGpj3hdz6s
|
|
||||||
Yxb+4+UypEZkiHRWEHJURMDFHd6hB99tipKjp7BBH3ZgoBaljkXvkEeQMc8UD9z5
|
|
||||||
3eDmB9cmQodDED9qSYK8cX9iOSP5tQFIKB1dXHQWwr/SxqIST6TLcDwtHSaYDBXJ
|
|
||||||
3+oU9+wLdt+gGFeN+x4ka7mO4j1pGBa0j1qcHbJSd9jGb0TeUUtet42V44me6lp0
|
|
||||||
DoogyX13uHrwf8kCzeJtKlUMbDM+65GOzrKmlwIDAQABAoIBAF6vFMp+lz4RteSh
|
|
||||||
Wm8m1FGAVwWVUpStOlcGClynFpTi0L88XYT3K7UMStQSttBDlqRv0ysdZF+ia+lj
|
|
||||||
bbKLdvHyFp8CJzX/AB4YZgyJlKzEYFtuBhbaHZu5hIMyU5W+OELSTCznV0p7w4C8
|
|
||||||
CGLLr+FTdhfCo1QU9NJn6fa9s2/XRdSClBBalAHYs0ZS7ZckaF/sPiC/VapfBMet
|
|
||||||
qjJXNYiO6pXYriGWKF9zdAMfk2CM0BVWbnwQZkMSEQirrTcJwm3ezyloXCv2nywK
|
|
||||||
/VzbUT1HJVyzo5oAwTd0MwDc2oEMiFzlfO028zY4LDltpia+SyWvFi5NaIqzFESc
|
|
||||||
yLgJacECgYEA3jvH+ZQHQf42Md8TCciokaYvwWIKJdk4WRjbvE5cBZekyXAm7/3b
|
|
||||||
/1VFDKsy2RPlfmfHP3wy9rlnjzsRveB5qaclgS8aI67AYsWd/yRgfRatl7Ve9bHl
|
|
||||||
LY6VM5L/DZTxykcqivwjc77XoDuBfUKs6tyuSLQku+FOTbLtNYlUCHECgYEA6nkR
|
|
||||||
lkXufyLmDhNb3093RsYvPcs1kGaIIGTnz3cxWNh485DgsyLBuYQ5ugupQkzM8YSt
|
|
||||||
ohDTmVpggqjlXQxCg0Zw8gkEV0v8KsLGjn1CuTJg/mBArXlelq1FEeRAYC9/YfOz
|
|
||||||
ocXegHV7wDKKtcraNZFsEc7Z0LwbC9wtzSFG44cCgYASkMX1CLPOhJE8e1lY0OWc
|
|
||||||
PVjx++HDJbF6aAQ7aARyBygiF/d4xylw3EvHcinuTqY2eC8CE7siN3z6T0H9Ldqc
|
|
||||||
HLWaZDf30SqLVd0MKprQ+GsKKIHFXtY5hxbZ1ybtmIrWjjl0oPnJOqFC5pW7xC0z
|
|
||||||
9bmtozcKZxkmjpMYjN9zUQKBgQCqV6KLRerqunPgLfhE1/qTlE+l2QflDFhBEI3I
|
|
||||||
j5NuNHZKnSphehK7sHAv1WD2Jc2OeRGb+BWCB8Ktqf5YBxwbOwW7EQnyUeW1OyP9
|
|
||||||
SMs8uHj21P6oCNDLLr5LLUQHnPoyM1aBZLstICzziMR1JhY5bJjSpzBfEQmlKCSu
|
|
||||||
LkrN6QKBgQCRXrBJRUxeJj7wCnCSq0Clf9NhCpQnwo4bEx8sKlj8K8ku8MvwQwoM
|
|
||||||
3KfWc7bOl6A2/mM/k4yoHtBMM9X9xqYtsgeFhxuiWBcfTmTxWh73LQ48Kgbrgodt
|
|
||||||
6yTccnjr7OtBidD85c6lgjAUgcL43QY8mlw0OhzXAZ2R5HWFp4ht+w==
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,18 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIC9TCCAd+gAwIBAgIRAJ6IIisIZxL86oe3oeoAgWUwCwYJKoZIhvcNAQELMCYx
|
|
||||||
ETAPBgNVBAoTCFF1aWNrVExTMREwDwYDVQQDEwhRdWlja1RMUzAeFw0xNjAxMjgw
|
|
||||||
MDQyMzNaFw0xOTAxMTIwMDQyMzNaMBMxETAPBgNVBAoTCFF1aWNrVExTMIIBIjAN
|
|
||||||
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3IXUwqSdO2QTj2ET6fJPGe+KWVnt
|
|
||||||
QCQQWjkWVpOz8L2A29BRvv9z6lYNf9sOM0Xb5IUAgoZ/s3U6LNYT/RWYFBfeo40r
|
|
||||||
Xd/MNKAn0kFsSb6BIKmUwPqFeqc8wiPX6yY4SbF1sUTkCTkw3yFHg/AIlwmhpFH3
|
|
||||||
9mAmV+x0kTzFR/78ZDD5CUNS59bbu+7UqB06YrJuVEwPY98YixSPXTcaKimsUe+K
|
|
||||||
IY8FQ6yN6l27MK56wlj4hw2gYz+cyBUBCExCgYMQlOSg2ilH4qYyFvccSDUH7jTA
|
|
||||||
NwpsIBfdoUVbI+j2ivn+ZGD614LtIStGgUu0mDDVxVOWnRvq/z7LMaa2jwIDAQAB
|
|
||||||
ozUwMzAOBgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYDVR0T
|
|
||||||
AQH/BAIwADALBgkqhkiG9w0BAQsDggEBAJq3JzTLrIWCF8rHLTTm1icE9PjOO0sV
|
|
||||||
a1wrmdJ6NwRbJ66dLZ/4G/NZjVOnce9WFHYLFSEG+wx5YVUPuJXpJaSdy0h8F0Uw
|
|
||||||
hiJwgeVsGg7vcf4G6mWHrsauDOhylnD31UtYPX1Ao/jcntyyf+gCQpY1J/B8l1yU
|
|
||||||
LNOwvWLVLpZwZ4ehbKA/UnDXgA+3uHvpzl//cPe0cnt+Mhrgzk5mIMwVR6zCZw1G
|
|
||||||
oVutAHpv2PXxRwTMu51J+QtSL2b2w3mGHxDLpmz8UdXOtkxdpmDT8kIOtX0T5yGL
|
|
||||||
29F3fa81iZPs02GWjSGOfOzmCCvaA4C5KJvY/WulF7OOgwvrBpQwqTI=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEA3IXUwqSdO2QTj2ET6fJPGe+KWVntQCQQWjkWVpOz8L2A29BR
|
|
||||||
vv9z6lYNf9sOM0Xb5IUAgoZ/s3U6LNYT/RWYFBfeo40rXd/MNKAn0kFsSb6BIKmU
|
|
||||||
wPqFeqc8wiPX6yY4SbF1sUTkCTkw3yFHg/AIlwmhpFH39mAmV+x0kTzFR/78ZDD5
|
|
||||||
CUNS59bbu+7UqB06YrJuVEwPY98YixSPXTcaKimsUe+KIY8FQ6yN6l27MK56wlj4
|
|
||||||
hw2gYz+cyBUBCExCgYMQlOSg2ilH4qYyFvccSDUH7jTANwpsIBfdoUVbI+j2ivn+
|
|
||||||
ZGD614LtIStGgUu0mDDVxVOWnRvq/z7LMaa2jwIDAQABAoIBAD2tiNZv6DImSXo+
|
|
||||||
sq0qQomEf/OBvWPFMnWppd/NK/TXa+UPHO4I0MjoDJqIEC6zCU+fC4d2St1MmlrT
|
|
||||||
/X85vPFRw8mGwGxfHeRSLxEVj04I5GDYTWy0JQUrJUk/cTKp2/Bwm/RaylTyFAM0
|
|
||||||
caYrSpvD69vjuTDFr7PDxM6iaqM53zK/vD8kCe81z+wN0UbAKsLlUOKztjH6SzL9
|
|
||||||
uVOkekIT/j3L2xxyQhjmhfA3TuCP4uNK/+6/4ovl9Nj4pQsFomsCk4phgqy9SOm1
|
|
||||||
4yufmVd8k7J3cppMlMPNc+7tqe2Xn593Y8QT95y3yhtkFECF70yBw64HMDDpA22p
|
|
||||||
5b/JV9ECgYEA9H4RBXOwbdjcpCa9H3mFjHqUQCqNme1vOSGiflZh9KBCDKgdqugm
|
|
||||||
KHpvAECADie0p6XRHpxRvufKnGFkJwedfeiKz51T+0dqgPxWncYT1TC+cAjOSzfM
|
|
||||||
wBpUOcAyvTTviwGbg4bLanHo4remzCbcnRvHQX4YfPFCjT9GhsU+XEUCgYEA5ubz
|
|
||||||
IlSu1wwFJpoO24ZykGUyqGUQXzR0NrXiLrpF0764qjmHyF8SPJPv1XegSxP/nUTz
|
|
||||||
SjVfJ7wye/X9qlOpBY8mzy9qQMMKc1cQBV1yVW8IRZ7pMYQZO7qmrZD/DWTa5qWt
|
|
||||||
pqSbIH2FKedELsKJA/SBtczKjspOdDKyh0UelsMCgYA7DyTfc0XAEy2hPXZb3wgC
|
|
||||||
mi2rnlvcPf2rCFPvPsCkzf2GfynDehaVmpWrsuj8Al1iTezI/yvD+Mv5oJEH2JAT
|
|
||||||
tROq+S8rOOIiTFJEBHAQBJlMCOSESPNdyD5mQOZAzEO9CWNejzYd/WwrL//Luut5
|
|
||||||
zBcC3AngTIsuAYXw0j6xHQKBgQDamkAJep7k3W5q82OplgoUhpqFLtlnKSP1QBFZ
|
|
||||||
J+U/6Mqv7jONEeUUEQL42H6bVd2kqUikMw9ZcSVikquLfBUDPFoDwOIZWg4k0IJM
|
|
||||||
cgHyvGHad+5SgLva/oUawbGWnqtXvfc/U4vCINPXrimxE1/grLW4xp/mu8W24OCA
|
|
||||||
jIG/PQKBgD/Apl+sfqiB/6ONBjjIswA4yFkEXHSZNpAgcPwhA+cO5D0afEWz2HIx
|
|
||||||
VeOh5NjN1EL0hX8clFW4bfkK1Vr0kjvbMUXnBWaibUgpiVQl9O9WjaKQLZrp4sRu
|
|
||||||
x2kJ07Qn6ri7f/lsqOELZwBy95iHWRdePptaAKkRGxJstHI7dgUt
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,18 +0,0 @@
|
||||||
version: 0.1
|
|
||||||
loglevel: debug
|
|
||||||
storage:
|
|
||||||
cache:
|
|
||||||
blobdescriptor: inmemory
|
|
||||||
filesystem:
|
|
||||||
rootdirectory: /tmp/registry-dev
|
|
||||||
http:
|
|
||||||
addr: 0.0.0.0:5000
|
|
||||||
compatibility:
|
|
||||||
schema1:
|
|
||||||
enabled: true
|
|
||||||
auth:
|
|
||||||
token:
|
|
||||||
realm: "https://auth.localregistry:5559/token/"
|
|
||||||
issuer: "registry-test"
|
|
||||||
service: "registry-test"
|
|
||||||
rootcertbundle: "/etc/docker/registry/tokenbundle.pem"
|
|
|
@ -1,21 +0,0 @@
|
||||||
version: 0.1
|
|
||||||
loglevel: debug
|
|
||||||
storage:
|
|
||||||
cache:
|
|
||||||
blobdescriptor: inmemory
|
|
||||||
filesystem:
|
|
||||||
rootdirectory: /tmp/registry-dev
|
|
||||||
http:
|
|
||||||
addr: 0.0.0.0:5000
|
|
||||||
tls:
|
|
||||||
certificate: "/etc/docker/registry/localregistry.cert"
|
|
||||||
key: "/etc/docker/registry/localregistry.key"
|
|
||||||
compatibility:
|
|
||||||
schema1:
|
|
||||||
enabled: true
|
|
||||||
auth:
|
|
||||||
token:
|
|
||||||
realm: "https://auth.localregistry:5559/token/"
|
|
||||||
issuer: "registry-test"
|
|
||||||
service: "registry-test"
|
|
||||||
rootcertbundle: "/etc/docker/registry/tokenbundle.pem"
|
|
|
@ -1 +0,0 @@
|
||||||
testuser:$2y$05$T2MlBvkN1R/yICNnLuf1leOlOfAY0DvybctbbWUFKlojfkShVgn4m
|
|
|
@ -1,8 +0,0 @@
|
||||||
FROM dmcgowan/token-server@sha256:0eab50ebdff5b6b95b3addf4edbd8bd2f5b940f27b41b43c94afdf05863a81af
|
|
||||||
|
|
||||||
WORKDIR /
|
|
||||||
|
|
||||||
COPY ./.htpasswd /.htpasswd
|
|
||||||
COPY ./certs/auth.localregistry.cert /tls.cert
|
|
||||||
COPY ./certs/auth.localregistry.key /tls.key
|
|
||||||
COPY ./certs/signing.key /sign.key
|
|
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDHDCCAgagAwIBAgIRAKhhQMnqZx+hkOmoUYgPb+kwCwYJKoZIhvcNAQELMCYx
|
|
||||||
ETAPBgNVBAoTCFF1aWNrVExTMREwDwYDVQQDEwhRdWlja1RMUzAeFw0xNjAxMjgw
|
|
||||||
MDQyMzFaFw0xOTAxMTIwMDQyMzFaMDAxETAPBgNVBAoTCFF1aWNrVExTMRswGQYD
|
|
||||||
VQQDExJhdXRoLmxvY2FscmVnaXN0cnkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
|
||||||
ggEKAoIBAQD1tUf1EghBlIRrE83yF4zDgRu7vH2Jo0kygKJUWtQQe+DfXyjjE/fg
|
|
||||||
FdKnnoEjsIeF9hxNbTt0ldDz7/n97pbMhoiXULi9iq4jlgSzVL2XEAgrON0YSY/c
|
|
||||||
Lmmd1KSa/pOUZr2WMAYPZ+FdQfE1W7SMNbErPefBqYdFzpZ+esAtvbajYwIjl8Vy
|
|
||||||
9c4bidx4vgnNrR9GcFYibjC5sj8syh/OtbzzqiVGT8YcPpmMG6KNRkausa4gqpon
|
|
||||||
NKYG8C3WDaiPCLYKcvFrFfdEWF/m2oj14eXACXT9iwp8r4bsLgXrZwqcpKOWfVRu
|
|
||||||
qHC8aV476EYgxWCAOANExUdUaRt5wL/jAgMBAAGjPzA9MA4GA1UdDwEB/wQEAwIA
|
|
||||||
oDAMBgNVHRMBAf8EAjAAMB0GA1UdEQQWMBSCEmF1dGgubG9jYWxyZWdpc3RyeTAL
|
|
||||||
BgkqhkiG9w0BAQsDggEBABxPGK9FdGDxcLowNsExKnnZvmQT3H0u+Dux1gkp0AhH
|
|
||||||
KOrmx3LUENUKLSgotzx133tgOgR5lzAWVFy7bhLwlPhOslxf2oEfztsAMd/tY8rW
|
|
||||||
PrG2ZqYqlzEQQ9INbAc3woo5A3slN07uhP3F16jNqoMM4zRmw6Ba70CluGKT7x5+
|
|
||||||
xVjKoWITLjWDXT5m35PnsN8CpBaFzXYcod/5p9XwCFp0s+aNxfpZECCV/3yqIr+J
|
|
||||||
ALzroPh43FAlG96o4NyYZ2Msp63newN19R2+TgpV4nXuw2mLVDpvetP7RRqnpvj/
|
|
||||||
qwRgt5j4hFjJWb61M0ELL7A9fA71h1ImdGCvnArdBQs=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpAIBAAKCAQEA9bVH9RIIQZSEaxPN8heMw4Ebu7x9iaNJMoCiVFrUEHvg318o
|
|
||||||
4xP34BXSp56BI7CHhfYcTW07dJXQ8+/5/e6WzIaIl1C4vYquI5YEs1S9lxAIKzjd
|
|
||||||
GEmP3C5pndSkmv6TlGa9ljAGD2fhXUHxNVu0jDWxKz3nwamHRc6WfnrALb22o2MC
|
|
||||||
I5fFcvXOG4nceL4Jza0fRnBWIm4wubI/LMofzrW886olRk/GHD6ZjBuijUZGrrGu
|
|
||||||
IKqaJzSmBvAt1g2ojwi2CnLxaxX3RFhf5tqI9eHlwAl0/YsKfK+G7C4F62cKnKSj
|
|
||||||
ln1UbqhwvGleO+hGIMVggDgDRMVHVGkbecC/4wIDAQABAoIBAQCrsjXKRwOF8CZo
|
|
||||||
PLqZBWPT6hBbK+f9miC4LbNBhwbRTf9hl7mWlImOCTHe95/+NIk/Ty+P21jEqzwM
|
|
||||||
ehETJPoziX9BXaL6sEHnlBlMx1aEjStoKKA3LJBeqAAdzk4IEQVHmlO4824IreqJ
|
|
||||||
pF7Njnunzo0zTlr4tWJVoXsAfv5z9tNtdkxYBbIa0fjfGtlqXU3gLq58FCON3mB/
|
|
||||||
NGc0AyA1UFGp0FzpdEcwTGD4InsXbcmsl2l/VPBJuZbryITRqWs6BbK++80DRhNt
|
|
||||||
afMhP+IzKrWSCp0rBYrqqz6AevtlKdEfQK1yXPEjN/63QLMevt8mF/1JCp//TQnf
|
|
||||||
Z6bIQbAhAoGBAP7vFA0PcvoXt9MXvvAwrKY1s6pNw4nWPG27qY1/m+DkBwP8IQms
|
|
||||||
4AWGv1wscZzXJYTvaLO5/qjmGUj50ohcVEvyZJioh1pKXA8Chxvd6rBA/O/Lj5E0
|
|
||||||
3MOSA5Q0gxJ0Mhv0zGbbyN5fY8D8zhxoqQP4LoW+UdZG2Oi6JxsQ9c9dAoGBAPa8
|
|
||||||
U3bGuM5OGA9EWP7mkB/VnjDTL1aEIN3cOHbHIKwH/loxdYcNMBE7vwxV1CzgIzXT
|
|
||||||
wsL0iE15fQdK938u0+um8aH5QtbWNI8tdk1XVjEC/i3C7N6WVUutneCKUDb4QxiB
|
|
||||||
9OvWCbNNiN+xTKBBM93YlwO3GYfrW9Pmm9q1+hg/AoGBALJlUS22gun50PxaIJZq
|
|
||||||
KVcCO2DQnCYHki/j48mN4+HjD/m85M2lePrFCYIR48syTyIQer9SR5+frVAA6k/b
|
|
||||||
9G1VCQo+3MDVSkiCp1Nb3tBKGfYgB65ARMBinDiI6rPuNeaUTrkn0g+yxtaU0hLV
|
|
||||||
Nnj9omia/x+oYj+xjI4HN0xNAoGARy92dSJIV104m88ATip/EnAzP6ruUWu1f8z1
|
|
||||||
jW9OAdQckjEK03f+kjpGmGx61qekAPejjVO3r4KJi/0ZAtyjz61OsYiUvB748wYO
|
|
||||||
x6mW+HUAmHtQk7eTzE2+6vV8xx9BXGTCIPiTu+N2xfMFRIcLS8odZ7j/6LMCv1Qd
|
|
||||||
SzCNg0kCgYBaNlEs4pK1VxZZpEWwVmFpgIxfEfxLIaGrek6wBTcCn/VA2M0oHuez
|
|
||||||
mlMio8VY0yWPBJz30JflDiTmYIvteLPMHT0N0J6isiXLhzJSFI4+cAMLE2Q5v8rz
|
|
||||||
W+W5/L8YZeierW0qJat1BrgStaf5ZLpiOc9pKBSwycydPH5BfVdK/A==
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,18 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIC9TCCAd+gAwIBAgIQNS9SaFSFBN7Zvwjalrf2DDALBgkqhkiG9w0BAQswJjER
|
|
||||||
MA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE2MDEyODAw
|
|
||||||
NDIzMFoXDTE5MDExMjAwNDIzMFowJjERMA8GA1UEChMIUXVpY2tUTFMxETAPBgNV
|
|
||||||
BAMTCFF1aWNrVExTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu/Pf
|
|
||||||
fQ7VUTSXs12PRyrLDVDz7kPDbGNTt0vF7FYDmTTGOU3i62xZNOGuxBezAiVSV5A3
|
|
||||||
lopwsv4OH7DRtSaPn+XCt1JDALna2WrjT0MshypMd5o2c3jmGUfAKf5gjizgIoEl
|
|
||||||
d4e5aqEBuOQP+QCEde+8p8N1buQW+zMy9srM2O/7BFMIaQ07CWLlj3hIiF+L5rKD
|
|
||||||
L6dWtKT7INRmRwpuZZnThEWnBSNgayrWek6G0i3y8QYTfVA1SwA+H3grJxy5NrLp
|
|
||||||
GYXSmu2509mu0QAHhx05t1rJhwhFz/4sG7j8AggYeDXEqfQ/VIb/bvnW9bD+vrQ2
|
|
||||||
ZnICvxnzNMYBx23BkQIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAKQwDwYDVR0TAQH/
|
|
||||||
BAUwAwEB/zALBgkqhkiG9w0BAQsDggEBALvTi6E44Fltu83dFLVEj0kLtusI/TTH
|
|
||||||
Tw6upoB5pRG+7A75w0Ii8bvvd2tNpBOg+L+80xyIFqaNkXhLKTN4lgtd7WiCuyb/
|
|
||||||
w1BEuF/+RjCXhu6wQ/63ab46d6ctaQ1zjxlU2rQLQXQFALI8ntyn/TELc01HYkr2
|
|
||||||
x3NHlbnBNlgI2CKXPeUBzvBylTCcdYGwoa+2ZPdIsFjle2aCIBoZ+WNZlIbFwgLh
|
|
||||||
XCHwcbviC+thjqOneJpJZmRW9AxQ638ki6iGItdrJewCN/1dcL2KKjxnC5VHbpne
|
|
||||||
SOjEPNXihY08Brl8myhFNtRRKZ55MJIYzDtVQSkCaT91Q3XX9tSZadY=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,19 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDETCCAfugAwIBAgIQN7rT95eAy75c4n6/AsDJODALBgkqhkiG9w0BAQswJjER
|
|
||||||
MA8GA1UEChMIUXVpY2tUTFMxETAPBgNVBAMTCFF1aWNrVExTMB4XDTE2MDEyODAw
|
|
||||||
NDIzMloXDTE5MDExMjAwNDIzMlowKzERMA8GA1UEChMIUXVpY2tUTFMxFjAUBgNV
|
|
||||||
BAMTDWxvY2FscmVnaXN0cnkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
|
||||||
AQDLi75QEkl/qekcoOJlNv9y1IXvrbU2ssl4ViJiZRjWx+/CkyCCOyf9YUpAgRLr
|
|
||||||
Pskqde2mwhuNP8yBlOBb17Sapz7N3+hJi5j9vLBAFcamPeF3PqxjFv7j5TKkRmSI
|
|
||||||
dFYQclREwMUd3qEH322KkqOnsEEfdmCgFqWORe+QR5AxzxQP3Pnd4OYH1yZCh0MQ
|
|
||||||
P2pJgrxxf2I5I/m1AUgoHV1cdBbCv9LGohJPpMtwPC0dJpgMFcnf6hT37At236AY
|
|
||||||
V437HiRruY7iPWkYFrSPWpwdslJ32MZvRN5RS163jZXjiZ7qWnQOiiDJfXe4evB/
|
|
||||||
yQLN4m0qVQxsMz7rkY7OsqaXAgMBAAGjOjA4MA4GA1UdDwEB/wQEAwIAoDAMBgNV
|
|
||||||
HRMBAf8EAjAAMBgGA1UdEQQRMA+CDWxvY2FscmVnaXN0cnkwCwYJKoZIhvcNAQEL
|
|
||||||
A4IBAQAyUb3EuMaOylBeV8+4KeBiE4lxykDOwLLSk3jXRsVVtfJpX3v8l5vwo/Jf
|
|
||||||
iG8tzzz+7uiskI96u3TsekUtVkUxujfKevMP+369K/59s7NRmwwlFMyB2fvL14B2
|
|
||||||
oweVjWvM/8fZl6irtFdbJFXXRm7paKso5cmfImxhojAwohgcd4XTVLE/7juYa582
|
|
||||||
AaBdRuIiyL71MU9qa1mC5+57AaSLPYaPKpahemgYYkV1Z403Kd6rXchxdQ8JIAL8
|
|
||||||
+0oYTSC+svnz1tUU/V5E5id9LQaTmDN5iIVFhNpqAaZmR45UI86woWvnkMb8Ants
|
|
||||||
4aknwTwY3300PuTqBdQufvOFDRN5
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpAIBAAKCAQEAy4u+UBJJf6npHKDiZTb/ctSF7621NrLJeFYiYmUY1sfvwpMg
|
|
||||||
gjsn/WFKQIES6z7JKnXtpsIbjT/MgZTgW9e0mqc+zd/oSYuY/bywQBXGpj3hdz6s
|
|
||||||
Yxb+4+UypEZkiHRWEHJURMDFHd6hB99tipKjp7BBH3ZgoBaljkXvkEeQMc8UD9z5
|
|
||||||
3eDmB9cmQodDED9qSYK8cX9iOSP5tQFIKB1dXHQWwr/SxqIST6TLcDwtHSaYDBXJ
|
|
||||||
3+oU9+wLdt+gGFeN+x4ka7mO4j1pGBa0j1qcHbJSd9jGb0TeUUtet42V44me6lp0
|
|
||||||
DoogyX13uHrwf8kCzeJtKlUMbDM+65GOzrKmlwIDAQABAoIBAF6vFMp+lz4RteSh
|
|
||||||
Wm8m1FGAVwWVUpStOlcGClynFpTi0L88XYT3K7UMStQSttBDlqRv0ysdZF+ia+lj
|
|
||||||
bbKLdvHyFp8CJzX/AB4YZgyJlKzEYFtuBhbaHZu5hIMyU5W+OELSTCznV0p7w4C8
|
|
||||||
CGLLr+FTdhfCo1QU9NJn6fa9s2/XRdSClBBalAHYs0ZS7ZckaF/sPiC/VapfBMet
|
|
||||||
qjJXNYiO6pXYriGWKF9zdAMfk2CM0BVWbnwQZkMSEQirrTcJwm3ezyloXCv2nywK
|
|
||||||
/VzbUT1HJVyzo5oAwTd0MwDc2oEMiFzlfO028zY4LDltpia+SyWvFi5NaIqzFESc
|
|
||||||
yLgJacECgYEA3jvH+ZQHQf42Md8TCciokaYvwWIKJdk4WRjbvE5cBZekyXAm7/3b
|
|
||||||
/1VFDKsy2RPlfmfHP3wy9rlnjzsRveB5qaclgS8aI67AYsWd/yRgfRatl7Ve9bHl
|
|
||||||
LY6VM5L/DZTxykcqivwjc77XoDuBfUKs6tyuSLQku+FOTbLtNYlUCHECgYEA6nkR
|
|
||||||
lkXufyLmDhNb3093RsYvPcs1kGaIIGTnz3cxWNh485DgsyLBuYQ5ugupQkzM8YSt
|
|
||||||
ohDTmVpggqjlXQxCg0Zw8gkEV0v8KsLGjn1CuTJg/mBArXlelq1FEeRAYC9/YfOz
|
|
||||||
ocXegHV7wDKKtcraNZFsEc7Z0LwbC9wtzSFG44cCgYASkMX1CLPOhJE8e1lY0OWc
|
|
||||||
PVjx++HDJbF6aAQ7aARyBygiF/d4xylw3EvHcinuTqY2eC8CE7siN3z6T0H9Ldqc
|
|
||||||
HLWaZDf30SqLVd0MKprQ+GsKKIHFXtY5hxbZ1ybtmIrWjjl0oPnJOqFC5pW7xC0z
|
|
||||||
9bmtozcKZxkmjpMYjN9zUQKBgQCqV6KLRerqunPgLfhE1/qTlE+l2QflDFhBEI3I
|
|
||||||
j5NuNHZKnSphehK7sHAv1WD2Jc2OeRGb+BWCB8Ktqf5YBxwbOwW7EQnyUeW1OyP9
|
|
||||||
SMs8uHj21P6oCNDLLr5LLUQHnPoyM1aBZLstICzziMR1JhY5bJjSpzBfEQmlKCSu
|
|
||||||
LkrN6QKBgQCRXrBJRUxeJj7wCnCSq0Clf9NhCpQnwo4bEx8sKlj8K8ku8MvwQwoM
|
|
||||||
3KfWc7bOl6A2/mM/k4yoHtBMM9X9xqYtsgeFhxuiWBcfTmTxWh73LQ48Kgbrgodt
|
|
||||||
6yTccnjr7OtBidD85c6lgjAUgcL43QY8mlw0OhzXAZ2R5HWFp4ht+w==
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,18 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIC9TCCAd+gAwIBAgIRAJ6IIisIZxL86oe3oeoAgWUwCwYJKoZIhvcNAQELMCYx
|
|
||||||
ETAPBgNVBAoTCFF1aWNrVExTMREwDwYDVQQDEwhRdWlja1RMUzAeFw0xNjAxMjgw
|
|
||||||
MDQyMzNaFw0xOTAxMTIwMDQyMzNaMBMxETAPBgNVBAoTCFF1aWNrVExTMIIBIjAN
|
|
||||||
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3IXUwqSdO2QTj2ET6fJPGe+KWVnt
|
|
||||||
QCQQWjkWVpOz8L2A29BRvv9z6lYNf9sOM0Xb5IUAgoZ/s3U6LNYT/RWYFBfeo40r
|
|
||||||
Xd/MNKAn0kFsSb6BIKmUwPqFeqc8wiPX6yY4SbF1sUTkCTkw3yFHg/AIlwmhpFH3
|
|
||||||
9mAmV+x0kTzFR/78ZDD5CUNS59bbu+7UqB06YrJuVEwPY98YixSPXTcaKimsUe+K
|
|
||||||
IY8FQ6yN6l27MK56wlj4hw2gYz+cyBUBCExCgYMQlOSg2ilH4qYyFvccSDUH7jTA
|
|
||||||
NwpsIBfdoUVbI+j2ivn+ZGD614LtIStGgUu0mDDVxVOWnRvq/z7LMaa2jwIDAQAB
|
|
||||||
ozUwMzAOBgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYDVR0T
|
|
||||||
AQH/BAIwADALBgkqhkiG9w0BAQsDggEBAJq3JzTLrIWCF8rHLTTm1icE9PjOO0sV
|
|
||||||
a1wrmdJ6NwRbJ66dLZ/4G/NZjVOnce9WFHYLFSEG+wx5YVUPuJXpJaSdy0h8F0Uw
|
|
||||||
hiJwgeVsGg7vcf4G6mWHrsauDOhylnD31UtYPX1Ao/jcntyyf+gCQpY1J/B8l1yU
|
|
||||||
LNOwvWLVLpZwZ4ehbKA/UnDXgA+3uHvpzl//cPe0cnt+Mhrgzk5mIMwVR6zCZw1G
|
|
||||||
oVutAHpv2PXxRwTMu51J+QtSL2b2w3mGHxDLpmz8UdXOtkxdpmDT8kIOtX0T5yGL
|
|
||||||
29F3fa81iZPs02GWjSGOfOzmCCvaA4C5KJvY/WulF7OOgwvrBpQwqTI=
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,27 +0,0 @@
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEowIBAAKCAQEA3IXUwqSdO2QTj2ET6fJPGe+KWVntQCQQWjkWVpOz8L2A29BR
|
|
||||||
vv9z6lYNf9sOM0Xb5IUAgoZ/s3U6LNYT/RWYFBfeo40rXd/MNKAn0kFsSb6BIKmU
|
|
||||||
wPqFeqc8wiPX6yY4SbF1sUTkCTkw3yFHg/AIlwmhpFH39mAmV+x0kTzFR/78ZDD5
|
|
||||||
CUNS59bbu+7UqB06YrJuVEwPY98YixSPXTcaKimsUe+KIY8FQ6yN6l27MK56wlj4
|
|
||||||
hw2gYz+cyBUBCExCgYMQlOSg2ilH4qYyFvccSDUH7jTANwpsIBfdoUVbI+j2ivn+
|
|
||||||
ZGD614LtIStGgUu0mDDVxVOWnRvq/z7LMaa2jwIDAQABAoIBAD2tiNZv6DImSXo+
|
|
||||||
sq0qQomEf/OBvWPFMnWppd/NK/TXa+UPHO4I0MjoDJqIEC6zCU+fC4d2St1MmlrT
|
|
||||||
/X85vPFRw8mGwGxfHeRSLxEVj04I5GDYTWy0JQUrJUk/cTKp2/Bwm/RaylTyFAM0
|
|
||||||
caYrSpvD69vjuTDFr7PDxM6iaqM53zK/vD8kCe81z+wN0UbAKsLlUOKztjH6SzL9
|
|
||||||
uVOkekIT/j3L2xxyQhjmhfA3TuCP4uNK/+6/4ovl9Nj4pQsFomsCk4phgqy9SOm1
|
|
||||||
4yufmVd8k7J3cppMlMPNc+7tqe2Xn593Y8QT95y3yhtkFECF70yBw64HMDDpA22p
|
|
||||||
5b/JV9ECgYEA9H4RBXOwbdjcpCa9H3mFjHqUQCqNme1vOSGiflZh9KBCDKgdqugm
|
|
||||||
KHpvAECADie0p6XRHpxRvufKnGFkJwedfeiKz51T+0dqgPxWncYT1TC+cAjOSzfM
|
|
||||||
wBpUOcAyvTTviwGbg4bLanHo4remzCbcnRvHQX4YfPFCjT9GhsU+XEUCgYEA5ubz
|
|
||||||
IlSu1wwFJpoO24ZykGUyqGUQXzR0NrXiLrpF0764qjmHyF8SPJPv1XegSxP/nUTz
|
|
||||||
SjVfJ7wye/X9qlOpBY8mzy9qQMMKc1cQBV1yVW8IRZ7pMYQZO7qmrZD/DWTa5qWt
|
|
||||||
pqSbIH2FKedELsKJA/SBtczKjspOdDKyh0UelsMCgYA7DyTfc0XAEy2hPXZb3wgC
|
|
||||||
mi2rnlvcPf2rCFPvPsCkzf2GfynDehaVmpWrsuj8Al1iTezI/yvD+Mv5oJEH2JAT
|
|
||||||
tROq+S8rOOIiTFJEBHAQBJlMCOSESPNdyD5mQOZAzEO9CWNejzYd/WwrL//Luut5
|
|
||||||
zBcC3AngTIsuAYXw0j6xHQKBgQDamkAJep7k3W5q82OplgoUhpqFLtlnKSP1QBFZ
|
|
||||||
J+U/6Mqv7jONEeUUEQL42H6bVd2kqUikMw9ZcSVikquLfBUDPFoDwOIZWg4k0IJM
|
|
||||||
cgHyvGHad+5SgLva/oUawbGWnqtXvfc/U4vCINPXrimxE1/grLW4xp/mu8W24OCA
|
|
||||||
jIG/PQKBgD/Apl+sfqiB/6ONBjjIswA4yFkEXHSZNpAgcPwhA+cO5D0afEWz2HIx
|
|
||||||
VeOh5NjN1EL0hX8clFW4bfkK1Vr0kjvbMUXnBWaibUgpiVQl9O9WjaKQLZrp4sRu
|
|
||||||
x2kJ07Qn6ri7f/lsqOELZwBy95iHWRdePptaAKkRGxJstHI7dgUt
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
|
@ -1,21 +0,0 @@
|
||||||
version: 0.1
|
|
||||||
loglevel: debug
|
|
||||||
storage:
|
|
||||||
cache:
|
|
||||||
blobdescriptor: inmemory
|
|
||||||
filesystem:
|
|
||||||
rootdirectory: /tmp/registry-dev
|
|
||||||
http:
|
|
||||||
addr: 0.0.0.0:5000
|
|
||||||
tls:
|
|
||||||
certificate: "/etc/docker/registry/localregistry.cert"
|
|
||||||
key: "/etc/docker/registry/localregistry.key"
|
|
||||||
compatibility:
|
|
||||||
schema1:
|
|
||||||
enabled: true
|
|
||||||
auth:
|
|
||||||
token:
|
|
||||||
realm: "https://auth.localregistry:5556/token/"
|
|
||||||
issuer: "registry-test"
|
|
||||||
service: "registry-test"
|
|
||||||
rootcertbundle: "/etc/docker/registry/tokenbundle.pem"
|
|
|
@ -1,38 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3/registry/api/errcode"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errGroup = "tokenserver"
|
|
||||||
|
|
||||||
// ErrorBadTokenOption is returned when a token parameter is invalid
|
|
||||||
ErrorBadTokenOption = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
|
||||||
Value: "BAD_TOKEN_OPTION",
|
|
||||||
Message: "bad token option",
|
|
||||||
Description: `This error may be returned when a request for a
|
|
||||||
token contains an option which is not valid`,
|
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
|
||||||
})
|
|
||||||
|
|
||||||
// ErrorMissingRequiredField is returned when a required form field is missing
|
|
||||||
ErrorMissingRequiredField = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
|
||||||
Value: "MISSING_REQUIRED_FIELD",
|
|
||||||
Message: "missing required field",
|
|
||||||
Description: `This error may be returned when a request for a
|
|
||||||
token does not contain a required form field`,
|
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
|
||||||
})
|
|
||||||
|
|
||||||
// ErrorUnsupportedValue is returned when a form field has an unsupported value
|
|
||||||
ErrorUnsupportedValue = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
|
||||||
Value: "UNSUPPORTED_VALUE",
|
|
||||||
Message: "unsupported value",
|
|
||||||
Description: `This error may be returned when a request for a
|
|
||||||
token contains a form field with an unsupported value`,
|
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
|
||||||
})
|
|
||||||
)
|
|
|
@ -1,431 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"math/big"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
dcontext "github.com/distribution/distribution/v3/context"
|
|
||||||
"github.com/distribution/distribution/v3/registry/api/errcode"
|
|
||||||
"github.com/distribution/distribution/v3/registry/auth"
|
|
||||||
_ "github.com/distribution/distribution/v3/registry/auth/htpasswd"
|
|
||||||
"github.com/docker/libtrust"
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
var enforceRepoClass bool
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var (
|
|
||||||
issuer = &TokenIssuer{}
|
|
||||||
pkFile string
|
|
||||||
addr string
|
|
||||||
debug bool
|
|
||||||
err error
|
|
||||||
|
|
||||||
passwdFile string
|
|
||||||
realm string
|
|
||||||
|
|
||||||
cert string
|
|
||||||
certKey string
|
|
||||||
)
|
|
||||||
|
|
||||||
flag.StringVar(&issuer.Issuer, "issuer", "distribution-token-server", "Issuer string for token")
|
|
||||||
flag.StringVar(&pkFile, "key", "", "Private key file")
|
|
||||||
flag.StringVar(&addr, "addr", "localhost:8080", "Address to listen on")
|
|
||||||
flag.BoolVar(&debug, "debug", false, "Debug mode")
|
|
||||||
|
|
||||||
flag.StringVar(&passwdFile, "passwd", ".htpasswd", "Passwd file")
|
|
||||||
flag.StringVar(&realm, "realm", "", "Authentication realm")
|
|
||||||
|
|
||||||
flag.StringVar(&cert, "tlscert", "", "Certificate file for TLS")
|
|
||||||
flag.StringVar(&certKey, "tlskey", "", "Certificate key for TLS")
|
|
||||||
|
|
||||||
flag.BoolVar(&enforceRepoClass, "enforce-class", false, "Enforce policy for single repository class")
|
|
||||||
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
logrus.SetLevel(logrus.DebugLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
if pkFile == "" {
|
|
||||||
issuer.SigningKey, err = libtrust.GenerateECP256PrivateKey()
|
|
||||||
if err != nil {
|
|
||||||
logrus.Fatalf("Error generating private key: %v", err)
|
|
||||||
}
|
|
||||||
logrus.Debugf("Using newly generated key with id %s", issuer.SigningKey.KeyID())
|
|
||||||
} else {
|
|
||||||
issuer.SigningKey, err = libtrust.LoadKeyFile(pkFile)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Fatalf("Error loading key file %s: %v", pkFile, err)
|
|
||||||
}
|
|
||||||
logrus.Debugf("Loaded private key with id %s", issuer.SigningKey.KeyID())
|
|
||||||
}
|
|
||||||
|
|
||||||
if realm == "" {
|
|
||||||
logrus.Fatalf("Must provide realm")
|
|
||||||
}
|
|
||||||
|
|
||||||
ac, err := auth.GetAccessController("htpasswd", map[string]interface{}{
|
|
||||||
"realm": realm,
|
|
||||||
"path": passwdFile,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
logrus.Fatalf("Error initializing access controller: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make configurable
|
|
||||||
issuer.Expiration = 15 * time.Minute
|
|
||||||
|
|
||||||
ctx := dcontext.Background()
|
|
||||||
|
|
||||||
ts := &tokenServer{
|
|
||||||
issuer: issuer,
|
|
||||||
accessController: ac,
|
|
||||||
refreshCache: map[string]refreshToken{},
|
|
||||||
}
|
|
||||||
|
|
||||||
router := mux.NewRouter()
|
|
||||||
router.Path("/token/").Methods(http.MethodGet).Handler(handlerWithContext(ctx, ts.getToken))
|
|
||||||
router.Path("/token/").Methods(http.MethodPost).Handler(handlerWithContext(ctx, ts.postToken))
|
|
||||||
|
|
||||||
if cert == "" {
|
|
||||||
err = http.ListenAndServe(addr, router)
|
|
||||||
} else if certKey == "" {
|
|
||||||
logrus.Fatalf("Must provide certficate (-tlscert) and key (-tlskey)")
|
|
||||||
} else {
|
|
||||||
err = http.ListenAndServeTLS(addr, cert, certKey, router)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logrus.Infof("Error serving: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handlerWithContext wraps the given context-aware handler by setting up the
|
|
||||||
// request context from a base context.
|
|
||||||
func handlerWithContext(ctx context.Context, handler func(context.Context, http.ResponseWriter, *http.Request)) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ctx := dcontext.WithRequest(ctx, r)
|
|
||||||
logger := dcontext.GetRequestLogger(ctx)
|
|
||||||
ctx = dcontext.WithLogger(ctx, logger)
|
|
||||||
|
|
||||||
handler(ctx, w, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleError(ctx context.Context, err error, w http.ResponseWriter) {
|
|
||||||
ctx, w = dcontext.WithResponseWriter(ctx, w)
|
|
||||||
|
|
||||||
if serveErr := errcode.ServeJSON(w, err); serveErr != nil {
|
|
||||||
dcontext.GetResponseLogger(ctx).Errorf("error sending error response: %v", serveErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dcontext.GetResponseLogger(ctx).Info("application error")
|
|
||||||
}
|
|
||||||
|
|
||||||
var refreshCharacters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
||||||
|
|
||||||
const refreshTokenLength = 15
|
|
||||||
|
|
||||||
func newRefreshToken() string {
|
|
||||||
s := make([]rune, refreshTokenLength)
|
|
||||||
max := int64(len(refreshCharacters))
|
|
||||||
for i := range s {
|
|
||||||
randInt, err := rand.Int(rand.Reader, big.NewInt(max))
|
|
||||||
// let '0' serves the failure case
|
|
||||||
if err != nil {
|
|
||||||
logrus.Infof("Error on making refersh token: %v", err)
|
|
||||||
randInt = big.NewInt(0)
|
|
||||||
}
|
|
||||||
s[i] = refreshCharacters[randInt.Int64()]
|
|
||||||
}
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
type refreshToken struct {
|
|
||||||
subject string
|
|
||||||
service string
|
|
||||||
}
|
|
||||||
|
|
||||||
type tokenServer struct {
|
|
||||||
issuer *TokenIssuer
|
|
||||||
accessController auth.AccessController
|
|
||||||
refreshCache map[string]refreshToken
|
|
||||||
}
|
|
||||||
|
|
||||||
type tokenResponse struct {
|
|
||||||
Token string `json:"access_token"`
|
|
||||||
RefreshToken string `json:"refresh_token,omitempty"`
|
|
||||||
ExpiresIn int `json:"expires_in,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var repositoryClassCache = map[string]string{}
|
|
||||||
|
|
||||||
func filterAccessList(ctx context.Context, scope string, requestedAccessList []auth.Access) []auth.Access {
|
|
||||||
if !strings.HasSuffix(scope, "/") {
|
|
||||||
scope = scope + "/"
|
|
||||||
}
|
|
||||||
grantedAccessList := make([]auth.Access, 0, len(requestedAccessList))
|
|
||||||
for _, access := range requestedAccessList {
|
|
||||||
if access.Type == "repository" {
|
|
||||||
if !strings.HasPrefix(access.Name, scope) {
|
|
||||||
dcontext.GetLogger(ctx).Debugf("Resource scope not allowed: %s", access.Name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if enforceRepoClass {
|
|
||||||
if class, ok := repositoryClassCache[access.Name]; ok {
|
|
||||||
if class != access.Class {
|
|
||||||
dcontext.GetLogger(ctx).Debugf("Different repository class: %q, previously %q", access.Class, class)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else if strings.EqualFold(access.Action, "push") {
|
|
||||||
repositoryClassCache[access.Name] = access.Class
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if access.Type == "registry" {
|
|
||||||
if access.Name != "catalog" {
|
|
||||||
dcontext.GetLogger(ctx).Debugf("Unknown registry resource: %s", access.Name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// TODO: Limit some actions to "admin" users
|
|
||||||
} else {
|
|
||||||
dcontext.GetLogger(ctx).Debugf("Skipping unsupported resource type: %s", access.Type)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
grantedAccessList = append(grantedAccessList, access)
|
|
||||||
}
|
|
||||||
return grantedAccessList
|
|
||||||
}
|
|
||||||
|
|
||||||
type acctSubject struct{}
|
|
||||||
|
|
||||||
func (acctSubject) String() string { return "acctSubject" }
|
|
||||||
|
|
||||||
type requestedAccess struct{}
|
|
||||||
|
|
||||||
func (requestedAccess) String() string { return "requestedAccess" }
|
|
||||||
|
|
||||||
type grantedAccess struct{}
|
|
||||||
|
|
||||||
func (grantedAccess) String() string { return "grantedAccess" }
|
|
||||||
|
|
||||||
// getToken handles authenticating the request and authorizing access to the
|
|
||||||
// requested scopes.
|
|
||||||
func (ts *tokenServer) getToken(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
|
||||||
dcontext.GetLogger(ctx).Info("getToken")
|
|
||||||
|
|
||||||
params := r.URL.Query()
|
|
||||||
service := params.Get("service")
|
|
||||||
scopeSpecifiers := params["scope"]
|
|
||||||
var offline bool
|
|
||||||
if offlineStr := params.Get("offline_token"); offlineStr != "" {
|
|
||||||
var err error
|
|
||||||
offline, err = strconv.ParseBool(offlineStr)
|
|
||||||
if err != nil {
|
|
||||||
handleError(ctx, ErrorBadTokenOption.WithDetail(err), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
requestedAccessList := ResolveScopeSpecifiers(ctx, scopeSpecifiers)
|
|
||||||
|
|
||||||
authorizedCtx, err := ts.accessController.Authorized(ctx, requestedAccessList...)
|
|
||||||
if err != nil {
|
|
||||||
challenge, ok := err.(auth.Challenge)
|
|
||||||
if !ok {
|
|
||||||
handleError(ctx, err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get response context.
|
|
||||||
ctx, w = dcontext.WithResponseWriter(ctx, w)
|
|
||||||
|
|
||||||
challenge.SetHeaders(r, w)
|
|
||||||
handleError(ctx, errcode.ErrorCodeUnauthorized.WithDetail(challenge.Error()), w)
|
|
||||||
|
|
||||||
dcontext.GetResponseLogger(ctx).Info("get token authentication challenge")
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx = authorizedCtx
|
|
||||||
|
|
||||||
username := dcontext.GetStringValue(ctx, "auth.user.name")
|
|
||||||
|
|
||||||
ctx = context.WithValue(ctx, acctSubject{}, username)
|
|
||||||
ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, acctSubject{}))
|
|
||||||
|
|
||||||
dcontext.GetLogger(ctx).Info("authenticated client")
|
|
||||||
|
|
||||||
ctx = context.WithValue(ctx, requestedAccess{}, requestedAccessList)
|
|
||||||
ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, requestedAccess{}))
|
|
||||||
|
|
||||||
grantedAccessList := filterAccessList(ctx, username, requestedAccessList)
|
|
||||||
ctx = context.WithValue(ctx, grantedAccess{}, grantedAccessList)
|
|
||||||
ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, grantedAccess{}))
|
|
||||||
|
|
||||||
token, err := ts.issuer.CreateJWT(username, service, grantedAccessList)
|
|
||||||
if err != nil {
|
|
||||||
handleError(ctx, err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dcontext.GetLogger(ctx).Info("authorized client")
|
|
||||||
|
|
||||||
response := tokenResponse{
|
|
||||||
Token: token,
|
|
||||||
ExpiresIn: int(ts.issuer.Expiration.Seconds()),
|
|
||||||
}
|
|
||||||
|
|
||||||
if offline {
|
|
||||||
response.RefreshToken = newRefreshToken()
|
|
||||||
ts.refreshCache[response.RefreshToken] = refreshToken{
|
|
||||||
subject: username,
|
|
||||||
service: service,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, w = dcontext.WithResponseWriter(ctx, w)
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
json.NewEncoder(w).Encode(response)
|
|
||||||
|
|
||||||
dcontext.GetResponseLogger(ctx).Info("get token complete")
|
|
||||||
}
|
|
||||||
|
|
||||||
type postTokenResponse struct {
|
|
||||||
Token string `json:"access_token"`
|
|
||||||
Scope string `json:"scope,omitempty"`
|
|
||||||
ExpiresIn int `json:"expires_in,omitempty"`
|
|
||||||
IssuedAt string `json:"issued_at,omitempty"`
|
|
||||||
RefreshToken string `json:"refresh_token,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// postToken handles authenticating the request and authorizing access to the
|
|
||||||
// requested scopes.
|
|
||||||
func (ts *tokenServer) postToken(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
|
||||||
grantType := r.PostFormValue("grant_type")
|
|
||||||
if grantType == "" {
|
|
||||||
handleError(ctx, ErrorMissingRequiredField.WithDetail("missing grant_type value"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
service := r.PostFormValue("service")
|
|
||||||
if service == "" {
|
|
||||||
handleError(ctx, ErrorMissingRequiredField.WithDetail("missing service value"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
clientID := r.PostFormValue("client_id")
|
|
||||||
if clientID == "" {
|
|
||||||
handleError(ctx, ErrorMissingRequiredField.WithDetail("missing client_id value"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var offline bool
|
|
||||||
switch r.PostFormValue("access_type") {
|
|
||||||
case "", "online":
|
|
||||||
case "offline":
|
|
||||||
offline = true
|
|
||||||
default:
|
|
||||||
handleError(ctx, ErrorUnsupportedValue.WithDetail("unknown access_type value"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
requestedAccessList := ResolveScopeList(ctx, r.PostFormValue("scope"))
|
|
||||||
|
|
||||||
var subject string
|
|
||||||
var rToken string
|
|
||||||
switch grantType {
|
|
||||||
case "refresh_token":
|
|
||||||
rToken = r.PostFormValue("refresh_token")
|
|
||||||
if rToken == "" {
|
|
||||||
handleError(ctx, ErrorUnsupportedValue.WithDetail("missing refresh_token value"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rt, ok := ts.refreshCache[rToken]
|
|
||||||
if !ok || rt.service != service {
|
|
||||||
handleError(ctx, errcode.ErrorCodeUnauthorized.WithDetail("invalid refresh token"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
subject = rt.subject
|
|
||||||
case "password":
|
|
||||||
ca, ok := ts.accessController.(auth.CredentialAuthenticator)
|
|
||||||
if !ok {
|
|
||||||
handleError(ctx, ErrorUnsupportedValue.WithDetail("password grant type not supported"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
subject = r.PostFormValue("username")
|
|
||||||
if subject == "" {
|
|
||||||
handleError(ctx, ErrorUnsupportedValue.WithDetail("missing username value"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
password := r.PostFormValue("password")
|
|
||||||
if password == "" {
|
|
||||||
handleError(ctx, ErrorUnsupportedValue.WithDetail("missing password value"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := ca.AuthenticateUser(subject, password); err != nil {
|
|
||||||
handleError(ctx, errcode.ErrorCodeUnauthorized.WithDetail("invalid credentials"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
handleError(ctx, ErrorUnsupportedValue.WithDetail("unknown grant_type value"), w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = context.WithValue(ctx, acctSubject{}, subject)
|
|
||||||
ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, acctSubject{}))
|
|
||||||
|
|
||||||
dcontext.GetLogger(ctx).Info("authenticated client")
|
|
||||||
|
|
||||||
ctx = context.WithValue(ctx, requestedAccess{}, requestedAccessList)
|
|
||||||
ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, requestedAccess{}))
|
|
||||||
|
|
||||||
grantedAccessList := filterAccessList(ctx, subject, requestedAccessList)
|
|
||||||
ctx = context.WithValue(ctx, grantedAccess{}, grantedAccessList)
|
|
||||||
ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, grantedAccess{}))
|
|
||||||
|
|
||||||
token, err := ts.issuer.CreateJWT(subject, service, grantedAccessList)
|
|
||||||
if err != nil {
|
|
||||||
handleError(ctx, err, w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dcontext.GetLogger(ctx).Info("authorized client")
|
|
||||||
|
|
||||||
response := postTokenResponse{
|
|
||||||
Token: token,
|
|
||||||
ExpiresIn: int(ts.issuer.Expiration.Seconds()),
|
|
||||||
IssuedAt: time.Now().UTC().Format(time.RFC3339),
|
|
||||||
Scope: ToScopeList(grantedAccessList),
|
|
||||||
}
|
|
||||||
|
|
||||||
if offline {
|
|
||||||
rToken = newRefreshToken()
|
|
||||||
ts.refreshCache[rToken] = refreshToken{
|
|
||||||
subject: subject,
|
|
||||||
service: service,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if rToken != "" {
|
|
||||||
response.RefreshToken = rToken
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, w = dcontext.WithResponseWriter(ctx, w)
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
json.NewEncoder(w).Encode(response)
|
|
||||||
|
|
||||||
dcontext.GetResponseLogger(ctx).Info("post token complete")
|
|
||||||
}
|
|
|
@ -1,220 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
dcontext "github.com/distribution/distribution/v3/context"
|
|
||||||
"github.com/distribution/distribution/v3/registry/auth"
|
|
||||||
"github.com/distribution/distribution/v3/registry/auth/token"
|
|
||||||
"github.com/docker/libtrust"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ResolveScopeSpecifiers converts a list of scope specifiers from a token
|
|
||||||
// request's `scope` query parameters into a list of standard access objects.
|
|
||||||
func ResolveScopeSpecifiers(ctx context.Context, scopeSpecs []string) []auth.Access {
|
|
||||||
requestedAccessSet := make(map[auth.Access]struct{}, 2*len(scopeSpecs))
|
|
||||||
|
|
||||||
for _, scopeSpecifier := range scopeSpecs {
|
|
||||||
// There should be 3 parts, separated by a `:` character.
|
|
||||||
parts := strings.SplitN(scopeSpecifier, ":", 3)
|
|
||||||
|
|
||||||
if len(parts) != 3 {
|
|
||||||
dcontext.GetLogger(ctx).Infof("ignoring unsupported scope format %s", scopeSpecifier)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
resourceType, resourceName, actions := parts[0], parts[1], parts[2]
|
|
||||||
|
|
||||||
resourceType, resourceClass := splitResourceClass(resourceType)
|
|
||||||
if resourceType == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actions should be a comma-separated list of actions.
|
|
||||||
for _, action := range strings.Split(actions, ",") {
|
|
||||||
requestedAccess := auth.Access{
|
|
||||||
Resource: auth.Resource{
|
|
||||||
Type: resourceType,
|
|
||||||
Class: resourceClass,
|
|
||||||
Name: resourceName,
|
|
||||||
},
|
|
||||||
Action: action,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add this access to the requested access set.
|
|
||||||
requestedAccessSet[requestedAccess] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
requestedAccessList := make([]auth.Access, 0, len(requestedAccessSet))
|
|
||||||
for requestedAccess := range requestedAccessSet {
|
|
||||||
requestedAccessList = append(requestedAccessList, requestedAccess)
|
|
||||||
}
|
|
||||||
|
|
||||||
return requestedAccessList
|
|
||||||
}
|
|
||||||
|
|
||||||
var typeRegexp = regexp.MustCompile(`^([a-z0-9]+)(\([a-z0-9]+\))?$`)
|
|
||||||
|
|
||||||
func splitResourceClass(t string) (string, string) {
|
|
||||||
matches := typeRegexp.FindStringSubmatch(t)
|
|
||||||
if len(matches) < 2 {
|
|
||||||
return "", ""
|
|
||||||
}
|
|
||||||
if len(matches) == 2 || len(matches[2]) < 2 {
|
|
||||||
return matches[1], ""
|
|
||||||
}
|
|
||||||
return matches[1], matches[2][1 : len(matches[2])-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolveScopeList converts a scope list from a token request's
|
|
||||||
// `scope` parameter into a list of standard access objects.
|
|
||||||
func ResolveScopeList(ctx context.Context, scopeList string) []auth.Access {
|
|
||||||
scopes := strings.Split(scopeList, " ")
|
|
||||||
return ResolveScopeSpecifiers(ctx, scopes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func scopeString(a auth.Access) string {
|
|
||||||
if a.Class != "" {
|
|
||||||
return fmt.Sprintf("%s(%s):%s:%s", a.Type, a.Class, a.Name, a.Action)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s:%s:%s", a.Type, a.Name, a.Action)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToScopeList converts a list of access to a
|
|
||||||
// scope list string
|
|
||||||
func ToScopeList(access []auth.Access) string {
|
|
||||||
var s []string
|
|
||||||
for _, a := range access {
|
|
||||||
s = append(s, scopeString(a))
|
|
||||||
}
|
|
||||||
return strings.Join(s, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
// TokenIssuer represents an issuer capable of generating JWT tokens
|
|
||||||
type TokenIssuer struct {
|
|
||||||
Issuer string
|
|
||||||
SigningKey libtrust.PrivateKey
|
|
||||||
Expiration time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateJWT creates and signs a JSON Web Token for the given subject and
|
|
||||||
// audience with the granted access.
|
|
||||||
func (issuer *TokenIssuer) CreateJWT(subject string, audience string, grantedAccessList []auth.Access) (string, error) {
|
|
||||||
// Make a set of access entries to put in the token's claimset.
|
|
||||||
resourceActionSets := make(map[auth.Resource]map[string]struct{}, len(grantedAccessList))
|
|
||||||
for _, access := range grantedAccessList {
|
|
||||||
actionSet, exists := resourceActionSets[access.Resource]
|
|
||||||
if !exists {
|
|
||||||
actionSet = map[string]struct{}{}
|
|
||||||
resourceActionSets[access.Resource] = actionSet
|
|
||||||
}
|
|
||||||
actionSet[access.Action] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
accessEntries := make([]*token.ResourceActions, 0, len(resourceActionSets))
|
|
||||||
for resource, actionSet := range resourceActionSets {
|
|
||||||
actions := make([]string, 0, len(actionSet))
|
|
||||||
for action := range actionSet {
|
|
||||||
actions = append(actions, action)
|
|
||||||
}
|
|
||||||
|
|
||||||
accessEntries = append(accessEntries, &token.ResourceActions{
|
|
||||||
Type: resource.Type,
|
|
||||||
Class: resource.Class,
|
|
||||||
Name: resource.Name,
|
|
||||||
Actions: actions,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
randomBytes := make([]byte, 15)
|
|
||||||
_, err := io.ReadFull(rand.Reader, randomBytes)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
randomID := base64.URLEncoding.EncodeToString(randomBytes)
|
|
||||||
|
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
signingHash := crypto.SHA256
|
|
||||||
var alg string
|
|
||||||
switch issuer.SigningKey.KeyType() {
|
|
||||||
case "RSA":
|
|
||||||
alg = "RS256"
|
|
||||||
case "EC":
|
|
||||||
alg = "ES256"
|
|
||||||
default:
|
|
||||||
panic(fmt.Errorf("unsupported signing key type %q", issuer.SigningKey.KeyType()))
|
|
||||||
}
|
|
||||||
|
|
||||||
joseHeader := token.Header{
|
|
||||||
Type: "JWT",
|
|
||||||
SigningAlg: alg,
|
|
||||||
}
|
|
||||||
|
|
||||||
if x5c := issuer.SigningKey.GetExtendedField("x5c"); x5c != nil {
|
|
||||||
joseHeader.X5c = x5c.([]string)
|
|
||||||
} else {
|
|
||||||
var jwkMessage json.RawMessage
|
|
||||||
jwkMessage, err = issuer.SigningKey.PublicKey().MarshalJSON()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
joseHeader.RawJWK = &jwkMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
exp := issuer.Expiration
|
|
||||||
if exp == 0 {
|
|
||||||
exp = 5 * time.Minute
|
|
||||||
}
|
|
||||||
|
|
||||||
claimSet := token.ClaimSet{
|
|
||||||
Issuer: issuer.Issuer,
|
|
||||||
Subject: subject,
|
|
||||||
Audience: []string{audience},
|
|
||||||
Expiration: now.Add(exp).Unix(),
|
|
||||||
NotBefore: now.Unix(),
|
|
||||||
IssuedAt: now.Unix(),
|
|
||||||
JWTID: randomID,
|
|
||||||
|
|
||||||
Access: accessEntries,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
joseHeaderBytes []byte
|
|
||||||
claimSetBytes []byte
|
|
||||||
)
|
|
||||||
|
|
||||||
if joseHeaderBytes, err = json.Marshal(joseHeader); err != nil {
|
|
||||||
return "", fmt.Errorf("unable to encode jose header: %s", err)
|
|
||||||
}
|
|
||||||
if claimSetBytes, err = json.Marshal(claimSet); err != nil {
|
|
||||||
return "", fmt.Errorf("unable to encode claim set: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
encodedJoseHeader := joseBase64Encode(joseHeaderBytes)
|
|
||||||
encodedClaimSet := joseBase64Encode(claimSetBytes)
|
|
||||||
encodingToSign := fmt.Sprintf("%s.%s", encodedJoseHeader, encodedClaimSet)
|
|
||||||
|
|
||||||
var signatureBytes []byte
|
|
||||||
if signatureBytes, _, err = issuer.SigningKey.Sign(strings.NewReader(encodingToSign), signingHash); err != nil {
|
|
||||||
return "", fmt.Errorf("unable to sign jwt payload: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
signature := joseBase64Encode(signatureBytes)
|
|
||||||
|
|
||||||
return fmt.Sprintf("%s.%s", encodingToSign, signature), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func joseBase64Encode(data []byte) string {
|
|
||||||
return strings.TrimRight(base64.URLEncoding.EncodeToString(data), "=")
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"encoding/base64"
|
|
||||||
"errors"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3/registry/auth"
|
|
||||||
"github.com/docker/libtrust"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCreateJWTSuccessWithEmptyACL(t *testing.T) {
|
|
||||||
key, err := rsa.GenerateKey(rand.Reader, 1024)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
pk, err := libtrust.FromCryptoPrivateKey(key)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
tokenIssuer := TokenIssuer{
|
|
||||||
Expiration: time.Duration(100),
|
|
||||||
Issuer: "localhost",
|
|
||||||
SigningKey: pk,
|
|
||||||
}
|
|
||||||
|
|
||||||
grantedAccessList := make([]auth.Access, 0)
|
|
||||||
token, err := tokenIssuer.CreateJWT("test", "test", grantedAccessList)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens := strings.Split(token, ".")
|
|
||||||
|
|
||||||
if len(token) == 0 {
|
|
||||||
t.Fatal("token not generated.")
|
|
||||||
}
|
|
||||||
|
|
||||||
json, err := decodeJWT(tokens[1])
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(json, "test") {
|
|
||||||
t.Fatal("Valid token was not generated.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeJWT(rawToken string) (string, error) {
|
|
||||||
data, err := joseBase64Decode(rawToken)
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.New("Error in Decoding base64 String")
|
|
||||||
}
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func joseBase64Decode(s string) (string, error) {
|
|
||||||
switch len(s) % 4 {
|
|
||||||
case 0:
|
|
||||||
case 2:
|
|
||||||
s += "=="
|
|
||||||
case 3:
|
|
||||||
s += "="
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
return "", errors.New("Invalid base64 String")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data, err := base64.StdEncoding.DecodeString(s)
|
|
||||||
if err != nil {
|
|
||||||
return "", err // errors.New("Error in Decoding base64 String")
|
|
||||||
}
|
|
||||||
return string(data), nil
|
|
||||||
}
|
|
Loading…
Reference in a new issue