diff --git a/.gitignore b/.gitignore index b04a8c8..18ebe81 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ # rspec failure tracking .rspec_status + +resources/registry_authentication/*.key +resources/registry_authentication/*.crt +resources/registry_authentication/htpasswd \ No newline at end of file diff --git a/bin/setup b/bin/setup index a859511..38b3a1e 100755 --- a/bin/setup +++ b/bin/setup @@ -18,5 +18,13 @@ then else echo "Running bundle install" bundle install + + echo "Creating self-signed certificate to use in tests" + openssl req -newkey rsa:2048 -nodes -keyout resources/registry_authentication/registry_auth.key -x509 -days 365 -out resources/registry_authentication/registry_auth.crt -subj "/C=CL/ST=Santiago/L=Santiago/O=dockerapi/OU=dockerapi/CN=dockerapi" + + echo "Creating htpasswd file to use in tests" + docker run --rm --entrypoint htpasswd registry:2.7.0 -Bbn janedoe password > resources/registry_authentication/htpasswd + docker image rm registry:2.7.0 echo "Run this script as root for further configurations" -fi \ No newline at end of file +fi + diff --git a/resources/registry_authentication/.keep b/resources/registry_authentication/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/endpoints/image_spec.rb b/spec/endpoints/image_spec.rb index 8498295..6020280 100644 --- a/spec/endpoints/image_spec.rb +++ b/spec/endpoints/image_spec.rb @@ -189,4 +189,63 @@ it { expect(subject.distribution(image).status).to eq(200) } it { expect(subject.distribution("doesn-exist").status).to eq(403) } end + + describe "authentication" do + original = "registry:2.7.0" + local = "localhost:5000/janedoe/test:latest" + before(:all) do + described_class.new.create(fromImage: original) + + container = Docker::API::Container.new + container.create( {name: "registry"}, { + Image: original, + HostConfig: { + PortBindings: {"5000/tcp": [ {HostIp: "0.0.0.0", HostPort: "5000"} ] }, + Binds: [ + "#{File.expand_path(File.dirname(__FILE__))}/../../resources/registry_authentication:/auth", + "#{File.expand_path(File.dirname(__FILE__))}/../../resources/registry_authentication:/certs"]}, + Env: [ + "REGISTRY_AUTH=htpasswd", + "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", + "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", + "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry_auth.crt", + "REGISTRY_HTTP_TLS_KEY=/certs/registry_auth.key", + + ], + }) + container.start("registry") + + described_class.new.tag(original, repo: local) + end + + describe ".push" do + it { expect(subject.push(local, {}, {username: "janedoe", password: "password"}).status).to eq(200) } + it { expect(subject.push(local, {}, {username: "janedoe", password: "password"}).json.last[:aux][:Size]).to be > 0 } + it { expect(subject.push(local, {}, {username: "janedoe", password: "wrong-password"}).status).to eq(200) } + it { expect(subject.push(local, {}, {username: "janedoe", password: "wrong-password"}).json.last[:error]).to match(/(unauthorized: authentication required)/) } + end + + describe ".create" do + it { expect(subject.create({fromImage: local}, {username: "janedoe", password: "password"}).status).to eq(200) } + it { expect(subject.create({fromImage: "localhost:5000/janedoe/doesnt-exist:latest"}, {username: "janedoe", password: "password"}).status).to eq(404) } + it { expect(subject.create({fromImage: local}, {username: "janedoe", password: "wrong-password"}).status).to eq(500) } + end + + describe ".distribute" do + it { expect(subject.distribution(local, {username: "janedoe", password: "password"}).status).to eq(200) } + it { expect(subject.distribution("localhost:5000/janedoe/doesnt-exist:latest", {username: "janedoe", password: "password"}).status).to eq(404) } + it { expect(subject.distribution(local, {username: "janedoe", password: "wrong-password"}).status).to eq(401) } + end + + after(:all) do + container = Docker::API::Container.new + container.stop("registry") + container.remove("registry") + + described_class.new.remove(original) + + Docker::API::Volume.new.prune + end + + end end \ No newline at end of file