From e611f1e9587c88f960b58e73000461d044139f10 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 19 Oct 2017 19:50:08 +0200
Subject: [PATCH 001/528] Adding a first draft for how to contribute
---
CONTRIBUTING.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 107 insertions(+)
create mode 100644 CONTRIBUTING.md
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..bb34922a
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,107 @@
+# Contributing guidelines
+
+This document describes how to contribute to the Local EGA project
+
+We thank you in advance :+1::tada: for taking the time to contribute whether with _code_ or with _ideas_.
+
+We use [Zenhub](https://www.zenhub.com/), the [Agile project management within Github](https://www.zenhub.com/blog/how-to-use-github-agile-project-management/).
+
+You should first [install it](https://www.zenhub.com/extension) if you want to contribute.
+
+This GitHub repository follows the [coding guidelines from NBIS](/NBISweden/development-guidelines).
+
+# Procedure
+
+1) Create an issue on Github, and talk to the team members on the NBIS
+ local-ega Slack channel
+
+ Request access to [Jonas Hagberg](https://nbis.se/about/staff/jonas-hagberg/) if you are not part of that channel
+
+2) Assign yourself to that issue or pick one already created.
+
+3) Discussions on how to proceed about that issue take place in the
+ comments on that issue, beforehand. The keyword here is
+ _beforehand_. It is usually a good idea to talk about it
+ first. Somebody might have already some pieces in place, we avoid
+ unnecessary work duplication and a waste of time and effort.
+
+4) Work on it (on a fork, or on a separate branch) as you wish. That's what `git` is good for.
+
+ Use comments in your code, choose variable and function names that
+ clearly show what you intent to implement.
+
+ Use [`git rebase -i`](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History) in
+ order to rewrite your history, and have meaningful commits. That
+ way, we avoid the 'Typo', 'Work In Progress (WIP)', or
+ 'Oops...forgot this or that' commits.
+
+ Limit the first line of your git commits to 72 characters or less.
+
+ Name your branch as you wish and prefix the name with:
+ * `feature/` if it is a code feature
+ * `hotfix/` if you are fixing an urgent bug
+
+
+6) Create a Pull Request (PR), so that your code is reviewed by the
+ admins on this repository. That PR should be connected to the
+ issue you are working on. Moreover, the PR should use `Estimate=1`,
+ should be connected to an `Epic`, a `Milestone` and a `User story` (or
+ several).
+
+ You can select the reviewers you want, but for the moment, it is
+ good taste to not ignore anyone (even if they don't review much of
+ the PR). At least, other developers will see that there was
+ progress made on some issue.
+
+ Talk to us so we prepare a dedicated branch that will pull your code.
+ Do **_not_** ask us to merge it into `master`.
+
+7) It is possible that your PR requires changes (because it creates
+ conflicts, or because some parts should be rewritten in a cleaner
+ manner, or because it does not follow the standards, or you're
+ requesting the wrong branch to pull your code, etc...) In that
+ case, a reviewer will request changes and describe them in the
+ comment section of the PR.
+
+ You then update your branch with new commits, and ping the reviewer
+ on the slack channel. (Yes, we respond better there).
+
+ Note that the comments _in the PR_ are not used to discuss the
+ _how_ and _why_ of that issue. These discussions are not about the
+ issue itself but about _a solution_ to that issue.
+
+ Recall that discussions about the issue are good and prevent
+ duplicated or wasted efforts, but they take place in the comment
+ section of the related issue (see point 4), not in the PR.
+
+ In other words, we don't discuss when the work is done, and there
+ is no recourse, such that it's either accept or reject. We think we
+ can do better than that, and introduce a finer grained acceptance,
+ by involving _beforehand_ discussions so that everyone is on point.
+
+
+
+## Did you find a bug?
+
+* Ensure that the bug was not already reported by [searching under
+ Issues](/NBISweden/LocalEGA/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Abug%20%5BBUG%5D%20in%3Atitle).
+
+* Do **_not_** file it as a plain GitHub issue (we use the issue
+ system for our internal tasks (see Zenhub)). If you're unable to
+ find an (open) issue addressing the problem, [open a new
+ one](NBISweden/LocalEGA/issues/new?title=%5BBUG%5D). Be sure to
+ prefix the issue title with **[BUG]** and to include:
+
+ ** a _clear_ description,
+ ** as much relevant information as possible, and
+ ** a _code sample_ or an (executable) _test case_ demonstrating the expected behavior that is not occurring.
+
+* If possible, use the following [template to report a bug](todo) /* TODO */
+
+
+
+----
+
+| Authors | NBIS System Developers |
+|-------------:|:-----------------------|
+| Last updated | October 19th, 2017 |
From 0a776ae380d9ec5ea983aeca32c3df9e3ae96aff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Fri, 20 Oct 2017 10:55:51 +0200
Subject: [PATCH 002/528] Adding AGILE, and PR in the dev branch
---
CONTRIBUTING.md | 85 +++++++++++++++++++++++++++++++------------------
1 file changed, 54 insertions(+), 31 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index bb34922a..c22fa0a1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,28 +4,56 @@ This document describes how to contribute to the Local EGA project
We thank you in advance :+1::tada: for taking the time to contribute whether with _code_ or with _ideas_.
-We use [Zenhub](https://www.zenhub.com/), the [Agile project management within Github](https://www.zenhub.com/blog/how-to-use-github-agile-project-management/).
+## AGILE project management
-You should first [install it](https://www.zenhub.com/extension) if you want to contribute.
+We use [Zenhub](https://www.zenhub.com/), the Agile project management within Github.
-This GitHub repository follows the [coding guidelines from NBIS](/NBISweden/development-guidelines).
+You should first [install it](https://www.zenhub.com/extension) if you want to contribute.
-# Procedure
+In short, the [AGILE method](https://www.zenhub.com/blog/how-to-use-github-agile-project-management/) helps developers organize themselves:
+
+* They decide about the tasks (not the managers)
+* Main Tasks should be divided into smaller manageable ones. The big
+ tasks are called `Epics`.
+* We have a given period (called Sprint) to work on a chosen
+ task. Here, a Sprint spans across 2 weeks.
+* We review the work done at the end of the Sprint, closing issues or
+ pushing them into the next Sprint. Ideally they are sub-divided in
+ case they encounter obstacles.
+* We have a short meeting every weekday at 9:30am. We call it a
+ _standup_ and we use it to keep everyone on point, and identify
+ quickly blockers. It's not a lengthy discussion. We ask:
+ - What did you get done yesterday (or last week, last month, etc.)?
+ - What are you working on now?
+ - What isn’t going well, and on what could you use help?
+
+## Procedure
1) Create an issue on Github, and talk to the team members on the NBIS
- local-ega Slack channel
+ local-ega Slack channel. You can alternatively pick one already
+ created.
- Request access to [Jonas Hagberg](https://nbis.se/about/staff/jonas-hagberg/) if you are not part of that channel
+> Contact
+> [Jonas Hagberg](https://nbis.se/about/staff/jonas-hagberg/) to
+> request access if you are not part of that channel already.
-2) Assign yourself to that issue or pick one already created.
+2) Assign yourself to that issue.
3) Discussions on how to proceed about that issue take place in the
- comments on that issue, beforehand. The keyword here is
- _beforehand_. It is usually a good idea to talk about it
- first. Somebody might have already some pieces in place, we avoid
- unnecessary work duplication and a waste of time and effort.
-
-4) Work on it (on a fork, or on a separate branch) as you wish. That's what `git` is good for.
+ comment section on that issue, beforehand.
+
+ The keyword here is _beforehand_. It is usually a good idea to talk
+ about it first. Somebody might have already some pieces in place,
+ we avoid unnecessary work duplication and a waste of time and
+ effort.
+
+4) Work on it (on a fork, or on a separate branch) as you wish. That's
+what `git` is good for. This GitHub repository follows
+the [coding guidelines from NBIS](/NBISweden/development-guidelines).
+
+ Name your branch as you wish and prefix the name with:
+ * `feature/` if it is a code feature
+ * `hotfix/` if you are fixing an urgent bug
Use comments in your code, choose variable and function names that
clearly show what you intent to implement.
@@ -37,26 +65,22 @@ This GitHub repository follows the [coding guidelines from NBIS](/NBISweden/deve
Limit the first line of your git commits to 72 characters or less.
- Name your branch as you wish and prefix the name with:
- * `feature/` if it is a code feature
- * `hotfix/` if you are fixing an urgent bug
-
-6) Create a Pull Request (PR), so that your code is reviewed by the
- admins on this repository. That PR should be connected to the
- issue you are working on. Moreover, the PR should use `Estimate=1`,
- should be connected to an `Epic`, a `Milestone` and a `User story` (or
- several).
+5) Create a Pull Request (PR), so that your code is reviewed by the
+ admins on this repository.
+
+ That PR should be connected to the issue you are working on.
+ Moreover, the PR should use `Estimate=1`, should be connected to an
+ `Epic`, a `Milestone` and a `User story` (or several).
You can select the reviewers you want, but for the moment, it is
good taste to not ignore anyone (even if they don't review much of
the PR). At least, other developers will see that there was
progress made on some issue.
- Talk to us so we prepare a dedicated branch that will pull your code.
- Do **_not_** ask us to merge it into `master`.
+ Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
-7) It is possible that your PR requires changes (because it creates
+6) It is possible that your PR requires changes (because it creates
conflicts, or because some parts should be rewritten in a cleaner
manner, or because it does not follow the standards, or you're
requesting the wrong branch to pull your code, etc...) In that
@@ -92,9 +116,9 @@ This GitHub repository follows the [coding guidelines from NBIS](/NBISweden/deve
one](NBISweden/LocalEGA/issues/new?title=%5BBUG%5D). Be sure to
prefix the issue title with **[BUG]** and to include:
- ** a _clear_ description,
- ** as much relevant information as possible, and
- ** a _code sample_ or an (executable) _test case_ demonstrating the expected behavior that is not occurring.
+ - a _clear_ description,
+ - as much relevant information as possible, and
+ - a _code sample_ or an (executable) _test case_ demonstrating the expected behavior that is not occurring.
* If possible, use the following [template to report a bug](todo) /* TODO */
@@ -102,6 +126,5 @@ This GitHub repository follows the [coding guidelines from NBIS](/NBISweden/deve
----
-| Authors | NBIS System Developers |
-|-------------:|:-----------------------|
-| Last updated | October 19th, 2017 |
+Thanks again,
+/NBIS System Developers
From bea26a57445e26ca7f009eb3ed71e0699ef04e48 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Tue, 24 Oct 2017 11:41:24 +0200
Subject: [PATCH 003/528] Add key-pair generation for users to bootstrapping
functionality.
---
docker/bootstrap/generate.sh | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index 71bec235..72cac264 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -136,10 +136,19 @@ function generate_password {
[[ -z $CEGA_MQ_PASSWORD ]] && CEGA_MQ_PASSWORD=$(generate_password 16)
EGA_USER_PASSWORD_JOHN=$(generate_password 16)
+${OPENSSL} genrsa -out $ABS_PRIVATE/cega/users/john.sec -passout pass:${EGA_USER_PASSWORD_JOHN} 2048
+${OPENSSL} rsa -in $ABS_PRIVATE/cega/users/john.sec -passin pass:${EGA_USER_PASSWORD_JOHN} -pubout -out $ABS_PRIVATE/cega/users/john.pub
+chmod 400 $ABS_PRIVATE/cega/users/john.sec
+EGA_USER_PUBKEY_JOHN=$(ssh-keygen -i -mPKCS8 -f $ABS_PRIVATE/cega/users/john.pub)
+
EGA_USER_PASSWORD_JANE=$(generate_password 16)
+${OPENSSL} genrsa -out $ABS_PRIVATE/cega/users/jane.sec -passout pass:${EGA_USER_PASSWORD_JANE} 2048
+${OPENSSL} rsa -in $ABS_PRIVATE/cega/users/jane.sec -passin pass:${EGA_USER_PASSWORD_JANE} -pubout -out $ABS_PRIVATE/cega/users/jane.pub
+chmod 400 $ABS_PRIVATE/cega/users/jane.sec
+EGA_USER_PUBKEY_JANE=$(ssh-keygen -i -mPKCS8 -f $ABS_PRIVATE/cega/users/jane.pub)
cat > $ABS_PRIVATE/.trace < $ABS_PRIVATE/cega/users/john.yml < $ABS_PRIVATE/cega/users/jane.yml <
Date: Tue, 24 Oct 2017 12:08:18 +0200
Subject: [PATCH 004/528] Make three users: Taylor with a password, Jane with a
key and John with both.
---
docker/bootstrap/generate.sh | 47 ++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 21 deletions(-)
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index 72cac264..5e2d84b2 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -147,29 +147,31 @@ ${OPENSSL} rsa -in $ABS_PRIVATE/cega/users/jane.sec -passin pass:${EGA_USER_PASS
chmod 400 $ABS_PRIVATE/cega/users/jane.sec
EGA_USER_PUBKEY_JANE=$(ssh-keygen -i -mPKCS8 -f $ABS_PRIVATE/cega/users/jane.pub)
+EGA_USER_PASSWORD_TAYLOR=$(generate_password 16)
+
cat > $ABS_PRIVATE/.trace < $ABS_PRIVATE/cega/users/john.yml < $ABS_PRIVATE/cega/users/jane.yml < $ABS_PRIVATE/cega/users/taylor.yml <
Date: Tue, 24 Oct 2017 13:07:04 +0200
Subject: [PATCH 005/528] Use ${OPENSSL} instead of openssl.
---
docker/bootstrap/generate.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index 5e2d84b2..91a5b3df 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -209,7 +209,7 @@ ${OPENSSL} req -x509 -newkey rsa:2048 -keyout $ABS_PRIVATE/certs/ssl.key -nodes
echo "Generating some fake EGA users"
cat > $ABS_PRIVATE/cega/users/john.yml < $ABS_PRIVATE/cega/users/jane.yml < $ABS_PRIVATE/cega/users/taylor.yml <
Date: Tue, 24 Oct 2017 13:57:43 +0200
Subject: [PATCH 006/528] Create requirements.txt for SNYK
Using SNYK to automate security test requires a manifest file.
https://support.snyk.io/getting-started/languages-support
Create this file from the information in setup.py
---
requirements.txt | 6 ++++++
1 file changed, 6 insertions(+)
create mode 100644 requirements.txt
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 00000000..5172a9a3
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,6 @@
+pika==0.11.0
+aiohttp==2.2.5
+pycryptodomex==3.4.5
+aiopg==0.13.0
+colorama==0.3.7
+aiohttp-jinja2==0.13.0
From 471909b7ecb374803e8856d5d6a148cc95a1a157 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Tue, 24 Oct 2017 14:17:18 +0200
Subject: [PATCH 007/528] Add Cucumber test-suite.
---
cucumber/.gitignore | 17 ++++++
cucumber/pom.xml | 57 +++++++++++++++++++
.../java/se/nbis/lega/cucumber/Tests.java | 13 +++++
.../lega/cucumber/steps/Authentication.java | 50 ++++++++++++++++
.../src/test/resources/authentication.feature | 7 +++
5 files changed, 144 insertions(+)
create mode 100644 cucumber/.gitignore
create mode 100644 cucumber/pom.xml
create mode 100644 cucumber/src/test/java/se/nbis/lega/cucumber/Tests.java
create mode 100644 cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
create mode 100644 cucumber/src/test/resources/authentication.feature
diff --git a/cucumber/.gitignore b/cucumber/.gitignore
new file mode 100644
index 00000000..7830780c
--- /dev/null
+++ b/cucumber/.gitignore
@@ -0,0 +1,17 @@
+# Log file
+*.log
+
+# Idea files
+.idea
+*.iml
+
+# Package Files #
+*.jar
+*.war
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+target
+out
\ No newline at end of file
diff --git a/cucumber/pom.xml b/cucumber/pom.xml
new file mode 100644
index 00000000..7de3e74e
--- /dev/null
+++ b/cucumber/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+ no.uio.ifi.lega
+ cucumber
+ 1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.8
+
+
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 1.2.5
+
+
+
+
+ commons-io
+ commons-io
+ 2.5
+ test
+
+
+ com.hierynomus
+ sshj
+ 0.22.0
+ test
+
+
+ info.cukes
+ cucumber-java8
+ ${cucumber.version}
+ test
+
+
+ info.cukes
+ cucumber-junit
+ ${cucumber.version}
+ test
+
+
+
+
\ No newline at end of file
diff --git a/cucumber/src/test/java/se/nbis/lega/cucumber/Tests.java b/cucumber/src/test/java/se/nbis/lega/cucumber/Tests.java
new file mode 100644
index 00000000..ce0f644c
--- /dev/null
+++ b/cucumber/src/test/java/se/nbis/lega/cucumber/Tests.java
@@ -0,0 +1,13 @@
+package se.nbis.lega.cucumber;
+
+import cucumber.api.CucumberOptions;
+import cucumber.api.junit.Cucumber;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(
+ format = {"pretty", "html:target/cucumber"},
+ features = "classpath:authentication.feature"
+)
+public class Tests {
+}
diff --git a/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
new file mode 100644
index 00000000..0a4e8fa0
--- /dev/null
+++ b/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -0,0 +1,50 @@
+package se.nbis.lega.cucumber.steps;
+
+import cucumber.api.java.Before;
+import cucumber.api.java8.En;
+import net.schmizz.sshj.SSHClient;
+import net.schmizz.sshj.sftp.SFTPClient;
+import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
+import org.junit.Assert;
+
+import java.io.File;
+import java.io.IOException;
+
+public class Authentication implements En {
+
+ private static final String USERNAME = "john";
+
+ private File privateKey;
+
+ private SFTPClient sftp;
+
+ @Before
+ public void setUp() throws IOException {
+ privateKey = new File("../docker/bootstrap/private/cega/users/" + USERNAME + ".sec");
+ }
+
+ public Authentication() {
+ Given("I have a private key", () -> Assert.assertNotNull(privateKey));
+
+ When("I try to connect to the LocalEGA inbox via SFTP using private key", () -> {
+ try {
+ SSHClient ssh = new SSHClient();
+ ssh.addHostKeyVerifier(new PromiscuousVerifier());
+ ssh.connect("localhost", 2222);
+ ssh.authPublickey(USERNAME, privateKey.getPath());
+ sftp = ssh.newSFTPClient();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ });
+
+ Then("the operation is successful", () -> {
+ try {
+ Assert.assertEquals("inbox", sftp.ls("/").iterator().next().getName());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/cucumber/src/test/resources/authentication.feature b/cucumber/src/test/resources/authentication.feature
new file mode 100644
index 00000000..1c1c6d80
--- /dev/null
+++ b/cucumber/src/test/resources/authentication.feature
@@ -0,0 +1,7 @@
+Feature: Authentication
+ As a user I want to be able to authenticate against LocalEGA inbox
+
+ Scenario: Authenticate against LocalEGA inbox using private key
+ Given I have a private key
+ When I try to connect to the LocalEGA inbox via SFTP using private key
+ Then the operation is successful
\ No newline at end of file
From 51446015a26c5f5c3dd015fdab04290f2b22f7bc Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Tue, 24 Oct 2017 16:26:51 +0200
Subject: [PATCH 008/528] Remove "--no-cache" from Makefile.
---
docker/images/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/images/Makefile b/docker/images/Makefile
index 849a5d8b..b9768fb8 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -6,7 +6,7 @@ all: $(EGA_IMAGES)
.PHONY: all $(EGA_IMAGES)
$(EGA_IMAGES):
- docker build --no-cache -t nbis/ega:$@ $@
+ docker build -t nbis/ega:$@ $@
clean:
docker images | awk '/none/{print $$3}' | while read n; do docker rmi $$n; done
From a5152811e738a94779c9dfdcda57e16f04afdeea Mon Sep 17 00:00:00 2001
From: Jonas Hagberg
Date: Wed, 25 Oct 2017 08:52:45 +0200
Subject: [PATCH 009/528] Added codacy batch
Added Batch from codacy.
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 42d7a2f0..0ce91a82 100644
--- a/README.md
+++ b/README.md
@@ -81,3 +81,5 @@ start.
The next step is to move the file from the staging area into the
vault. A verification step is included to ensure that the storing went
fine. After that, a message of completion is sent to Central EGA.
+
+[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3dd83b28ec2041889bfb13641da76c5b)](https://www.codacy.com/app/NBIS/LocalEGA?utm_source=github.com&utm_medium=referral&utm_content=NBISweden/LocalEGA&utm_campaign=Badge_Grade)
From 8f396b462880ea48e4597726fd53bffdf1cbc43c Mon Sep 17 00:00:00 2001
From: Jonas Hagberg
Date: Wed, 25 Oct 2017 09:01:26 +0200
Subject: [PATCH 010/528] Moved badge to under the Rubben
---
README.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 0ce91a82..88673bd9 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,8 @@
# NBIS repository for the Local EGA project
+[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3dd83b28ec2041889bfb13641da76c5b)](https://www.codacy.com/app/NBIS/LocalEGA?utm_source=github.com&utm_medium=referral&utm_content=NBISweden/LocalEGA&utm_campaign=Badge_Grade)
+
+
The [code](./src) is written in Python (3.6+).
You can provision and deploy the different components:
@@ -81,5 +84,3 @@ start.
The next step is to move the file from the staging area into the
vault. A verification step is included to ensure that the storing went
fine. After that, a message of completion is sent to Central EGA.
-
-[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3dd83b28ec2041889bfb13641da76c5b)](https://www.codacy.com/app/NBIS/LocalEGA?utm_source=github.com&utm_medium=referral&utm_content=NBISweden/LocalEGA&utm_campaign=Badge_Grade)
From 004ac747583dfbbe1fa0be22215d0866e050e32a Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Wed, 25 Oct 2017 11:41:38 +0200
Subject: [PATCH 011/528] Pass internal exceptions to outside.
---
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 0a4e8fa0..c40af112 100644
--- a/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -34,15 +34,15 @@ public Authentication() {
ssh.authPublickey(USERNAME, privateKey.getPath());
sftp = ssh.newSFTPClient();
} catch (Exception e) {
- e.printStackTrace();
+ throw new RuntimeException(e);
}
});
Then("the operation is successful", () -> {
try {
Assert.assertEquals("inbox", sftp.ls("/").iterator().next().getName());
- } catch (IOException e) {
- e.printStackTrace();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
}
});
}
From bea6fe0ed6b3d28e8cdad234a8ec5c31be84c954 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Wed, 25 Oct 2017 11:55:43 +0200
Subject: [PATCH 012/528] Rename groupId.
---
cucumber/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cucumber/pom.xml b/cucumber/pom.xml
index 7de3e74e..a7a9485c 100644
--- a/cucumber/pom.xml
+++ b/cucumber/pom.xml
@@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- no.uio.ifi.lega
+ se.nbis.lega
cucumber
1.0-SNAPSHOT
From 7041c9015c8f8ce06c7efdb5a3c13000a5864cfc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 25 Oct 2017 17:30:00 +0200
Subject: [PATCH 013/528] Adding review guidelines and rephrasing a bit
---
CONTRIBUTING.md | 43 +++++++++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c22fa0a1..dc44050f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,7 +8,8 @@ We thank you in advance :+1::tada: for taking the time to contribute whether wit
We use [Zenhub](https://www.zenhub.com/), the Agile project management within Github.
-You should first [install it](https://www.zenhub.com/extension) if you want to contribute.
+You should first [install it](https://www.zenhub.com/extension) if you want to contribute.
+You can also use the [Zenhub app](https://app.zenhub.com) if you wish.
In short, the [AGILE method](https://www.zenhub.com/blog/how-to-use-github-agile-project-management/) helps developers organize themselves:
@@ -70,17 +71,30 @@ the [coding guidelines from NBIS](/NBISweden/development-guidelines).
admins on this repository.
That PR should be connected to the issue you are working on.
- Moreover, the PR should use `Estimate=1`, should be connected to an
- `Epic`, a `Milestone` and a `User story` (or several).
-
- You can select the reviewers you want, but for the moment, it is
- good taste to not ignore anyone (even if they don't review much of
- the PR). At least, other developers will see that there was
- progress made on some issue.
+ Moreover, the PR:
+
+ - should use `Estimate=1`,
+ - should be connected to:
+ + an `Epic`,
+ + a `Milestone` and
+ + a `User story`
+ + ... or several.
+
+Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
+
+6) Selecting a review goes as follows: Pick one _main_ reviewer. It
+ is usually one that you had discussions with, and is somehow
+ connected to that issue. If this is not the case, pick several reviewers.
+
+ Note that, in turn, the main reviewer might ask another reviewer
+ for help. The approval of all reviewers is compulsory in order to
+ merge the PR. Moreover, the main reviewer is the one merging the
+ PR, not you.
+
+ Find more information on the [NBIS reviewing guidelines](/NBISweden/development-guidelines#how-we-do-code-reviews).
- Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
-6) It is possible that your PR requires changes (because it creates
+7) It is possible that your PR requires changes (because it creates
conflicts, or because some parts should be rewritten in a cleaner
manner, or because it does not follow the standards, or you're
requesting the wrong branch to pull your code, etc...) In that
@@ -98,10 +112,11 @@ the [coding guidelines from NBIS](/NBISweden/development-guidelines).
duplicated or wasted efforts, but they take place in the comment
section of the related issue (see point 4), not in the PR.
- In other words, we don't discuss when the work is done, and there
- is no recourse, such that it's either accept or reject. We think we
- can do better than that, and introduce a finer grained acceptance,
- by involving _beforehand_ discussions so that everyone is on point.
+ Essentially, we don't want to open discussions when the work is
+ done, and there is no recourse, such that it's either accept or
+ reject. We think we can do better than that, and introduce a finer
+ grained acceptance, by involving _beforehand_ discussions so that
+ everyone is on point.
From f5acee1ec33c000083bc5e3cfe72ce1d373f48e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 25 Oct 2017 18:17:00 +0200
Subject: [PATCH 014/528] Reformating for Codacy
---
docker/images/cega_mq/publish.py | 2 --
src/lega/__init__.py | 6 ++++--
src/lega/conf/__init__.py | 12 ++++++------
src/lega/ingest.py | 2 --
src/lega/monitor.py | 2 +-
src/lega/utils/amqp.py | 4 ++--
src/lega/utils/crypto.py | 13 ++++++-------
src/lega/utils/db.py | 2 +-
src/lega/utils/socket.py | 8 ++++----
src/lega/vault.py | 2 +-
src/lega/verify.py | 4 ++--
11 files changed, 27 insertions(+), 30 deletions(-)
diff --git a/docker/images/cega_mq/publish.py b/docker/images/cega_mq/publish.py
index ebaf4e0e..53ea7ba5 100644
--- a/docker/images/cega_mq/publish.py
+++ b/docker/images/cega_mq/publish.py
@@ -5,7 +5,6 @@
creation of a user or the ingestion of a file.
'''
-import sys
import argparse
import uuid
import json
@@ -29,7 +28,6 @@
args = parser.parse_args()
-
message = { 'elixir_id': args.user, 'filename': args.filename }
if args.enc:
message['encrypted_integrity'] = { 'hash': args.enc, 'algorithm': args.enc_algo, }
diff --git a/src/lega/__init__.py b/src/lega/__init__.py
index 974468bb..00c2eaaf 100644
--- a/src/lega/__init__.py
+++ b/src/lega/__init__.py
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
# __init__ is here so that we don't collapse in sys.path with another lega module
-f"""Local EGA library
-~~~~~~~~~~~~~~~~~~~~~
+"""\
+Local EGA library
+~~~~~~~~~~~~~~~~~
The lega package contains code to start a _Local EGA_.
See `https://github.com/NBISweden/LocalEGA` for a full documentation.
+
:copyright: (c) 2017, NBIS System Developers.
"""
diff --git a/src/lega/conf/__init__.py b/src/lega/conf/__init__.py
index f7b826e3..b08e2e1f 100644
--- a/src/lega/conf/__init__.py
+++ b/src/lega/conf/__init__.py
@@ -12,12 +12,13 @@
]
_loggers = {
- 'default': _here / 'loggers/default.yaml',
- 'debug': _here / 'loggers/debug.yaml',
- 'syslog': _here / 'loggers/syslog.yaml',
+ 'default': _here / 'loggers/default.yaml',
+ 'debug': _here / 'loggers/debug.yaml',
+ 'syslog': _here / 'loggers/syslog.yaml',
}
-f"""This module provides a dictionary-like with configuration settings.
+f"""\
+This module provides a dictionary-like with configuration settings.
It also loads the logging settings when `setup` is called.
The `--log ` argument is used to configuration where the logs go.
@@ -37,8 +38,8 @@
which case, it must end in `.yaml` or `.yml`.
See `https://github.com/NBISweden/LocalEGA` for a full documentation.
-:copyright: (c) 2017, NBIS System Developers.
+:copyright: (c) 2017, NBIS System Developers.
"""
class Configuration(configparser.ConfigParser):
@@ -110,7 +111,6 @@ def _load_log_file(self,filename):
print(f"Unsupported log format for {filename}", file=sys.stderr)
self.log_conf = None
-
def _load_log_conf(self,args=None):
# Finding the --log file
diff --git a/src/lega/ingest.py b/src/lega/ingest.py
index c6446435..890870fd 100644
--- a/src/lega/ingest.py
+++ b/src/lega/ingest.py
@@ -28,9 +28,7 @@
import logging
from pathlib import Path
import shutil
-import stat
import uuid
-from multiprocessing import Process, cpu_count
import ssl
from functools import partial
import asyncio
diff --git a/src/lega/monitor.py b/src/lega/monitor.py
index a4669c72..d93fa1ce 100644
--- a/src/lega/monitor.py
+++ b/src/lega/monitor.py
@@ -17,7 +17,7 @@
import logging
import argparse
from time import sleep
-
+
from .conf import CONF
from .utils import db
diff --git a/src/lega/utils/amqp.py b/src/lega/utils/amqp.py
index f8f47ea1..6945b885 100644
--- a/src/lega/utils/amqp.py
+++ b/src/lega/utils/amqp.py
@@ -41,8 +41,8 @@ def get_connection(domain, blocking=True):
'ca_certs' : CONF.get(domain,'cacert'),
'certfile' : CONF.get(domain,'cert'),
'keyfile' : CONF.get(domain,'keyfile'),
- 'cert_reqs': 2 #ssl.CERT_REQUIRED is actually
- }
+ 'cert_reqs': 2, #ssl.CERT_REQUIRED is actually
+ }
LOG.info(f'Getting a connection to {domain}')
LOG.debug(params)
diff --git a/src/lega/utils/crypto.py b/src/lega/utils/crypto.py
index dcb0eff3..d4138316 100644
--- a/src/lega/utils/crypto.py
+++ b/src/lega/utils/crypto.py
@@ -9,7 +9,6 @@
'''
import logging
-import io
import os
import asyncio
import asyncio.subprocess
@@ -91,20 +90,20 @@ def __init__(self, active_key, master_pubkey, hashAlgo, target_h, done):
encryption_key, mode, nonce = next(self.engine)
self.header = make_header(active_key, len(encryption_key), len(nonce), mode.encode())
-
+
LOG.info(f'Writing header to file: {self.header} (and enc key + nonce)')
header_b = (self.header + '\n').encode()
-
+
self.target_handler.write(header_b)
self.target_handler.write(encryption_key)
self.target_handler.write(nonce)
-
+
LOG.info('Setup target digest')
self.target_digest = sha256()
self.target_digest.update(header_b)
self.target_digest.update(encryption_key)
self.target_digest.update(nonce)
-
+
# And now, daddy...
super().__init__()
@@ -113,7 +112,7 @@ def connection_made(self, transport):
self.transport = transport
def pipe_data_received(self, fd, data):
- # Data is of size: 32768 or 65536 bytes
+ # Data is of size: 32768 or 65536 bytes
if not data:
return
if fd == 1:
@@ -188,7 +187,7 @@ async def _re_encrypt():
_err = exceptions.Checksum(hash_algo,f'for decrypted content of {enc_file}')
LOG.error(str(_err))
- if _err:
+ if _err is not None:
LOG.warning(f'Removing {target}')
os.remove(target)
raise _err
diff --git a/src/lega/utils/db.py b/src/lega/utils/db.py
index 15314397..d2926394 100644
--- a/src/lega/utils/db.py
+++ b/src/lega/utils/db.py
@@ -258,7 +258,7 @@ def wrapper(*args):
if isinstance(e,AssertionError):
raise e
- exc_type, exc_obj, exc_tb = sys.exc_info()
+ exc_type, _, exc_tb = sys.exc_info()
g = traceback.walk_tb(exc_tb)
frame, lineno = next(g) # that should be the decorator
try:
diff --git a/src/lega/utils/socket.py b/src/lega/utils/socket.py
index e285da85..50408d6e 100644
--- a/src/lega/utils/socket.py
+++ b/src/lega/utils/socket.py
@@ -1,14 +1,14 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
-'''
-Unix Domain Socket forwarding to remote machine and
-proxying remote requests to a given Unix Domain Socket.
+'''\
+Unix Domain Socket forwarding to remote machine and proxying remote requests to a given Unix Domain Socket.
Usefull to forward gpg requests to a remote GPG-agent.
:author: Frédéric Haziza
:copyright: (c) 2017, NBIS System Developers.
+
'''
import sys
@@ -147,7 +147,7 @@ def proxy():
keyfile = Path(args.keyfile).expanduser() if args.keyfile else None
syslog(LOG_DEBUG, f'Certfile: {certfile}')
syslog(LOG_DEBUG, f'Keyfile: {keyfile}')
- if (certfile and certfile.exists() and
+ if (certfile and certfile.exists() and
keyfile and keyfile.exists()):
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_ctx.load_cert_chain(certfile, keyfile)
diff --git a/src/lega/vault.py b/src/lega/vault.py
index 79b01ea1..bdfd3181 100644
--- a/src/lega/vault.py
+++ b/src/lega/vault.py
@@ -51,7 +51,7 @@ def work(data):
starget = str(target)
LOG.debug(f'Moving {filepath} to {target}')
shutil.move(str(filepath), starget)
-
+
# Mark it as processed in DB
db.finalize_file(file_id, starget, target.stat().st_size)
diff --git a/src/lega/verify.py b/src/lega/verify.py
index 4f228abd..e591c93d 100644
--- a/src/lega/verify.py
+++ b/src/lega/verify.py
@@ -29,13 +29,13 @@ def work(data):
'''Verifying that the file in the vault does decrypt properly'''
file_id = data['file_id']
- filename, org_hash, org_hash_algo, vault_filename, vault_checksum = db.get_details(file_id)
+ filename, _, org_hash_algo, vault_filename, vault_checksum = db.get_details(file_id)
if not checksum.is_valid(vault_filename, vault_checksum, hashAlgo='sha256'):
raise exceptions.VaultDecryption(vault_filename)
return { 'vault_name': vault_filename, 'org_name': filename }
-
+
def main(args=None):
if not args:
From 0ee1288f807e8c0b4cfb4b0ca414eff63c812856 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Wed, 25 Oct 2017 23:12:52 +0200
Subject: [PATCH 015/528] Add .travis.yml
---
.travis.yml | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 .travis.yml
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..c4c116b7
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,16 @@
+sudo: required
+
+language: generic
+
+services:
+ - docker
+
+script:
+ - cd docker
+ - make -C images
+ - docker run --rm -i -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/generate.sh -f
+ - bootstrap/populate.sh
+ - sudo chown -R $USER .
+ - docker-compose up -d
+ - cd ../cucumber
+ - mvn test -B
From d898440076d3fe06ec45ae08348cf991ee6b25ab Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Wed, 25 Oct 2017 23:53:18 +0200
Subject: [PATCH 016/528] Add Travis CI badge.
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 88673bd9..098c93a4 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# NBIS repository for the Local EGA project
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3dd83b28ec2041889bfb13641da76c5b)](https://www.codacy.com/app/NBIS/LocalEGA?utm_source=github.com&utm_medium=referral&utm_content=NBISweden/LocalEGA&utm_campaign=Badge_Grade)
-
+[![Build Status](https://travis-ci.org/NBISweden/LocalEGA.svg?branch=dev)](https://travis-ci.org/NBISweden/LocalEGA)
The [code](./src) is written in Python (3.6+).
From 4420152b735e3cf3b5afbff11c3dca31f39d19c1 Mon Sep 17 00:00:00 2001
From: Jonas Hagberg
Date: Thu, 26 Oct 2017 08:27:47 +0200
Subject: [PATCH 017/528] Create .snyk
So SNYK understand we using python 3.6
---
.snyk | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 .snyk
diff --git a/.snyk b/.snyk
new file mode 100644
index 00000000..aa05424f
--- /dev/null
+++ b/.snyk
@@ -0,0 +1,2 @@
+language-settings:
+ python: "3.6"
From 505a07bb48a1111461630994f3680614593bfaf2 Mon Sep 17 00:00:00 2001
From: Jonas Hagberg
Date: Thu, 26 Oct 2017 09:04:34 +0200
Subject: [PATCH 018/528] Update CONTRIBUTING.md
Fixed some grammar
---
CONTRIBUTING.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index dc44050f..3610a879 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,7 +8,7 @@ We thank you in advance :+1::tada: for taking the time to contribute whether wit
We use [Zenhub](https://www.zenhub.com/), the Agile project management within Github.
-You should first [install it](https://www.zenhub.com/extension) if you want to contribute.
+You should first [install it](https://www.zenhub.com/extension) if you want to contribute or just follow the project progress.
You can also use the [Zenhub app](https://app.zenhub.com) if you wish.
In short, the [AGILE method](https://www.zenhub.com/blog/how-to-use-github-agile-project-management/) helps developers organize themselves:
@@ -19,9 +19,9 @@ In short, the [AGILE method](https://www.zenhub.com/blog/how-to-use-github-agile
* We have a given period (called Sprint) to work on a chosen
task. Here, a Sprint spans across 2 weeks.
* We review the work done at the end of the Sprint, closing issues or
- pushing them into the next Sprint. Ideally they are sub-divided in
+ pushing them into the next Sprint. Ideally, they are sub-divided in
case they encounter obstacles.
-* We have a short meeting every weekday at 9:30am. We call it a
+* We have a short meeting every weekday at 09:30 am. We call it a
_standup_ and we use it to keep everyone on point, and identify
quickly blockers. It's not a lengthy discussion. We ask:
- What did you get done yesterday (or last week, last month, etc.)?
@@ -57,7 +57,7 @@ the [coding guidelines from NBIS](/NBISweden/development-guidelines).
* `hotfix/` if you are fixing an urgent bug
Use comments in your code, choose variable and function names that
- clearly show what you intent to implement.
+ clearly show what you intend to implement.
Use [`git rebase -i`](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History) in
order to rewrite your history, and have meaningful commits. That
@@ -83,7 +83,7 @@ the [coding guidelines from NBIS](/NBISweden/development-guidelines).
Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
6) Selecting a review goes as follows: Pick one _main_ reviewer. It
- is usually one that you had discussions with, and is somehow
+ is usually one that you had discussions with, and is somehow
connected to that issue. If this is not the case, pick several reviewers.
Note that, in turn, the main reviewer might ask another reviewer
@@ -101,7 +101,7 @@ Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
case, a reviewer will request changes and describe them in the
comment section of the PR.
- You then update your branch with new commits, and ping the reviewer
+ You then update your branch with new commits and ping the reviewer
on the slack channel. (Yes, we respond better there).
Note that the comments _in the PR_ are not used to discuss the
@@ -133,7 +133,7 @@ Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
- a _clear_ description,
- as much relevant information as possible, and
- - a _code sample_ or an (executable) _test case_ demonstrating the expected behavior that is not occurring.
+ - a _code sample_ or an (executable) _test case_ demonstrating the expected behaviour that is not occurring.
* If possible, use the following [template to report a bug](todo) /* TODO */
From 02fa6cfaea3108a477c1139b0f27853e27f44b0d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 26 Oct 2017 09:21:06 +0200
Subject: [PATCH 019/528] Formatting time
---
CONTRIBUTING.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3610a879..6a0d010b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -21,7 +21,7 @@ In short, the [AGILE method](https://www.zenhub.com/blog/how-to-use-github-agile
* We review the work done at the end of the Sprint, closing issues or
pushing them into the next Sprint. Ideally, they are sub-divided in
case they encounter obstacles.
-* We have a short meeting every weekday at 09:30 am. We call it a
+* We have a short meeting every weekday at 9:30 AM. We call it a
_standup_ and we use it to keep everyone on point, and identify
quickly blockers. It's not a lengthy discussion. We ask:
- What did you get done yesterday (or last week, last month, etc.)?
From dd323e41ec6476eff75514e2f98c1fa0ac083050 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 26 Oct 2017 10:49:19 +0200
Subject: [PATCH 020/528] Adding comment on integrated tests
---
CONTRIBUTING.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6a0d010b..5578f0d2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -95,11 +95,11 @@ Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
7) It is possible that your PR requires changes (because it creates
- conflicts, or because some parts should be rewritten in a cleaner
- manner, or because it does not follow the standards, or you're
- requesting the wrong branch to pull your code, etc...) In that
- case, a reviewer will request changes and describe them in the
- comment section of the PR.
+ conflicts, doesn't pass the integrated tests or because some parts
+ should be rewritten in a cleaner manner, or because it does not
+ follow the standards, or you're requesting the wrong branch to pull
+ your code, etc...) In that case, a reviewer will request changes
+ and describe them in the comment section of the PR.
You then update your branch with new commits and ping the reviewer
on the slack channel. (Yes, we respond better there).
From 850ece67658027ba621544c0b249fe4985475238 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Mon, 30 Oct 2017 11:36:19 +0100
Subject: [PATCH 021/528] Fix pycryptodomex installation.
---
docker/images/common/Dockerfile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/docker/images/common/Dockerfile b/docker/images/common/Dockerfile
index 0b8e59a4..2ac5e811 100644
--- a/docker/images/common/Dockerfile
+++ b/docker/images/common/Dockerfile
@@ -14,6 +14,8 @@ RUN yum -y update && \
RUN yum -y install https://centos7.iuscommunity.org/ius-release.rpm
RUN yum -y install gcc python36u python36u-pip
+RUN [[ -e /lib64/libpython3.6m.so ]] || ln -s /lib64/libpython3.6m.so.1.0 /lib64/libpython3.6m.so
+
# And some extra ones, to speed up booting the VMs
RUN pip3.6 install --upgrade pip && \
pip3.6 install PyYaml Markdown pika==0.11.0 aiohttp==2.2.5 pycryptodomex==3.4.5 aiopg==0.13.0 colorama==0.3.7 aiohttp-jinja2==0.13.0
From 7c6890d5d1ada07b8701999882782bfc829dddbf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 26 Oct 2017 00:05:13 +0200
Subject: [PATCH 022/528] Moving from fake CEGA to real (test) CEGA
---
docker/ega.yml | 24 +++++++++++++-----------
docker/entrypoints/inbox.sh | 4 +++-
src/auth/auth.conf.sample | 4 +++-
src/auth/cega.c | 26 ++++++++++++++++++++------
src/auth/config.c | 4 ++++
src/auth/config.h | 2 ++
6 files changed, 45 insertions(+), 19 deletions(-)
diff --git a/docker/ega.yml b/docker/ega.yml
index ee7a4616..d74dd35a 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -44,8 +44,10 @@ services:
hostname: ega_inbox
depends_on:
- db
- - cega_users
- env_file: .env.d/db
+# - cega_users
+ env_file:
+ - .env.d/db
+ - .env.d/cega
ports:
- "2222:22"
container_name: ega_inbox
@@ -140,15 +142,15 @@ services:
# image: nbis/ega:monitors
# command: ["rsyslogd", "-n"]
- # Faking Central EGA
- cega_users:
- build: images/cega_users
- image: nbis/ega:cega_users
- container_name: cega_users
- ports:
- - "9100:80"
- volumes:
- - ${CEGA_USERS}:/cega/users:rw
+ # # Faking Central EGA
+ # cega_users:
+ # build: images/cega_users
+ # image: nbis/ega:cega_users
+ # container_name: cega_users
+ # ports:
+ # - "9100:80"
+ # volumes:
+ # - ${CEGA_USERS}:/cega/users:rw
cega_mq:
build: images/cega_mq
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index 67a54dda..430c491c 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -23,7 +23,9 @@ debug = ok_why_not
db_connection = host=${EGA_DB_IP} port=5432 dbname=lega user=${POSTGRES_USER} password=${POSTGRES_PASSWORD} connect_timeout=1 sslmode=disable
enable_rest = yes
-rest_endpoint = http://cega_users/user/%s
+rest_endpoint = https://egatest.crg.eu/lega/v1/user/%s
+rest_user = ${CEGA_ENDPOINT_USER}
+rest_password = ${CEGA_ENDPOINT_PASSWORD}
##################
# NSS Queries
diff --git a/src/auth/auth.conf.sample b/src/auth/auth.conf.sample
index c7ca2475..82c70a82 100644
--- a/src/auth/auth.conf.sample
+++ b/src/auth/auth.conf.sample
@@ -7,7 +7,9 @@ db_connection = host=ega_db port=5432 dbname=lega user=postgres password=CHANGE-
enable_rest = yes
#rest_endpoint = https://ega.crg.eu/user/%s
-rest_endpoint = http://ega_frontend:9100/user/%s
+rest_endpoint = http://central_ega/user/%s
+rest_user = lega
+rest_password = change_me
##################
# NSS Queries
diff --git a/src/auth/cega.c b/src/auth/cega.c
index 00ee15fb..a3ab9eeb 100644
--- a/src/auth/cega.c
+++ b/src/auth/cega.c
@@ -52,10 +52,11 @@ fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop
bool success = false;
char endpoint[URL_SIZE];
struct curl_res_s *cres = NULL;
- json_object *json = NULL;
enum json_tokener_error jerr = json_tokener_success;
json_object *pwdh = NULL, *pubkey = NULL, *expiration = NULL;
-
+ json_object *json = NULL, *json_response = NULL, *json_result = NULL, *jobj = NULL;
+ char* endpoint_creds = NULL;
+
D("contacting cega for user: %s\n", username);
curl_global_init(CURL_GLOBAL_DEFAULT);
@@ -69,7 +70,7 @@ fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop
}
cres = (struct curl_res_s*)malloc(sizeof(struct curl_res_s));
-
+
curl_easy_setopt(curl, CURLOPT_NOPROGRESS , 1L ); /* shut off the progress meter */
curl_easy_setopt(curl, CURLOPT_URL , endpoint );
@@ -77,6 +78,11 @@ fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop
curl_easy_setopt(curl, CURLOPT_WRITEDATA , (void *)cres );
curl_easy_setopt(curl, CURLOPT_FAILONERROR , 1L ); /* when not 200 */
+ curl_easy_setopt(curl, CURLOPT_HTTPAUTH , CURLAUTH_BASIC);
+ endpoint_creds = (char*)malloc(1 + strlen(options->rest_user) + strlen(options->rest_password));
+ sprintf(endpoint_creds, "%s:%s", options->rest_user, options->rest_password);
+ curl_easy_setopt(curl, CURLOPT_USERPWD , endpoint_creds);
+
/* curl_easy_setopt(curl, CURLOPT_SSLCERT , options->ssl_cert); */
/* curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE , "PEM" ); */
@@ -100,9 +106,13 @@ fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop
goto BAIL_OUT;
}
- json_object_object_get_ex(json, "password_hash", &pwdh);
- json_object_object_get_ex(json, "pubkey", &pubkey);
- json_object_object_get_ex(json, "expiration", &expiration);
+ json_object_object_get_ex(json, "response", &json_response);
+ json_object_object_get_ex(json_response, "result", &json_result);
+
+ jobj = json_object_array_get_idx(json_result,0);
+ json_object_object_get_ex(jobj, "password", &pwdh);
+ json_object_object_get_ex(jobj, "public_key", &pubkey);
+ json_object_object_get_ex(jobj, "expiration", &expiration);
success = add_to_db(username,
json_object_get_string(pwdh),
@@ -112,6 +122,10 @@ fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop
BAIL_OUT:
if(!success) D("user %s not found\n", username);
if(cres) free(cres);
+ if(endpoint_creds) free(endpoint_creds);
+ json_object_put(jobj);
+ json_object_put(json_result);
+ json_object_put(json_response);
json_object_put(json);
curl_easy_cleanup(curl);
curl_global_cleanup();
diff --git a/src/auth/config.c b/src/auth/config.c
index 0f6a03ce..ec7a21dc 100644
--- a/src/auth/config.c
+++ b/src/auth/config.c
@@ -23,6 +23,8 @@ cleanconfig(void)
if(!options->pam_acct ) { free((char*)options->pam_acct); }
if(!options->pam_prompt ) { free((char*)options->pam_prompt); }
if(!options->rest_endpoint ) { free((char*)options->rest_endpoint); }
+ if(!options->rest_user ) { free((char*)options->rest_user); }
+ if(!options->rest_password ) { free((char*)options->rest_password); }
if(!options->ssl_cert ) { free((char*)options->ssl_cert); }
if(!options->skel ) { free((char*)options->skel); }
free(options);
@@ -98,6 +100,8 @@ readconfig(const char* configfile)
if(!strcmp(key, "pam_prompt" )) { options->pam_prompt = strdup(val); }
if(!strcmp(key, "skel" )) { options->skel = strdup(val); }
if(!strcmp(key, "rest_endpoint" )) { options->rest_endpoint = strdup(val); }
+ if(!strcmp(key, "rest_user" )) { options->rest_user = strdup(val); }
+ if(!strcmp(key, "rest_password" )) { options->rest_password = strdup(val); }
if(!strcmp(key, "rest_buffer_size" )) { options->rest_buffer_size = atoi(val); }
if(!strcmp(key, "ssl_cert" )) { options->ssl_cert = strdup(val); }
if(!strcmp(key, "enable_rest")) {
diff --git a/src/auth/config.h b/src/auth/config.h
index d59be695..b1201a7c 100644
--- a/src/auth/config.h
+++ b/src/auth/config.h
@@ -30,6 +30,8 @@ struct options_s {
/* ReST location */
bool with_rest; /* enable the lookup in case the entry is not found in the database cache */
const char* rest_endpoint; /* https://ega/user/ | returns a triplet in JSON format */
+ const char* rest_user;
+ const char* rest_password; /* for authentication: user:password */
int rest_buffer_size; /* 1024 */
const char* ssl_cert; /* path the SSL certificate to contact Central EGA */
From e9becd6a3d7013cd670a4fbc1054fc51001e8194 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Fri, 27 Oct 2017 12:46:05 +0200
Subject: [PATCH 023/528] Including Blowfish password hashing (used by
CentralEGA)
---
docker/entrypoints/inbox.sh | 2 +-
src/auth/Makefile | 26 +-
src/auth/backend.c | 19 +-
src/auth/blowfish/LINKS | 29 +
src/auth/blowfish/Makefile | 77 ++
src/auth/blowfish/PERFORMANCE | 30 +
src/auth/blowfish/README | 68 ++
src/auth/blowfish/crypt.3 | 575 ++++++++++++++
src/auth/blowfish/crypt.h | 24 +
src/auth/blowfish/crypt_blowfish.c | 907 +++++++++++++++++++++++
src/auth/blowfish/crypt_blowfish.h | 27 +
src/auth/blowfish/crypt_gensalt.c | 124 ++++
src/auth/blowfish/crypt_gensalt.h | 30 +
src/auth/blowfish/glibc-2.1.3-crypt.diff | 53 ++
src/auth/blowfish/glibc-2.14-crypt.diff | 55 ++
src/auth/blowfish/glibc-2.3.6-crypt.diff | 52 ++
src/auth/blowfish/ow-crypt.h | 43 ++
src/auth/blowfish/wrapper.c | 551 ++++++++++++++
src/auth/blowfish/x86.S | 203 +++++
19 files changed, 2883 insertions(+), 12 deletions(-)
create mode 100644 src/auth/blowfish/LINKS
create mode 100644 src/auth/blowfish/Makefile
create mode 100644 src/auth/blowfish/PERFORMANCE
create mode 100644 src/auth/blowfish/README
create mode 100644 src/auth/blowfish/crypt.3
create mode 100644 src/auth/blowfish/crypt.h
create mode 100644 src/auth/blowfish/crypt_blowfish.c
create mode 100644 src/auth/blowfish/crypt_blowfish.h
create mode 100644 src/auth/blowfish/crypt_gensalt.c
create mode 100644 src/auth/blowfish/crypt_gensalt.h
create mode 100644 src/auth/blowfish/glibc-2.1.3-crypt.diff
create mode 100644 src/auth/blowfish/glibc-2.14-crypt.diff
create mode 100644 src/auth/blowfish/glibc-2.3.6-crypt.diff
create mode 100644 src/auth/blowfish/ow-crypt.h
create mode 100644 src/auth/blowfish/wrapper.c
create mode 100644 src/auth/blowfish/x86.S
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index 430c491c..b26c7ec7 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -38,7 +38,7 @@ nss_add_user = SELECT insert_user(\$1,\$2,\$3)
##################
pam_auth = SELECT password_hash FROM users WHERE elixir_id = \$1 LIMIT 1
pam_acct = SELECT elixir_id FROM users WHERE elixir_id = \$1 and current_timestamp < last_accessed + expiration
-pam_prompt = wazzaaaa:
+#pam_prompt = wazzaaaa:
EOF
cat > /usr/local/bin/ega_ssh_keys.sh < in 2000-2011.
+# No copyright is claimed, and the software is hereby placed in the public
+# domain. In case this attempt to disclaim copyright and place the software
+# in the public domain is deemed null and void, then the software is
+# Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
+# general public under the following terms:
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted.
+#
+# There's ABSOLUTELY NO WARRANTY, express or implied.
+#
+# See crypt_blowfish.c for more information.
+#
+
+CC = gcc
+AS = $(CC)
+LD = $(CC)
+RM = rm -f
+CFLAGS = -W -Wall -Wbad-function-cast -Wcast-align -Wcast-qual -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wundef -Wpointer-arith -O2 -fomit-frame-pointer -funroll-loops
+ASFLAGS = -c
+LDFLAGS = -s
+
+BLOWFISH_OBJS = \
+ crypt_blowfish.o x86.o
+
+CRYPT_OBJS = \
+ $(BLOWFISH_OBJS) crypt_gensalt.o wrapper.o
+
+TEST_OBJS = \
+ $(BLOWFISH_OBJS) crypt_gensalt.o crypt_test.o
+
+TEST_THREADS_OBJS = \
+ $(BLOWFISH_OBJS) crypt_gensalt.o crypt_test_threads.o
+
+EXTRA_MANS = \
+ crypt_r.3 crypt_rn.3 crypt_ra.3 \
+ crypt_gensalt.3 crypt_gensalt_rn.3 crypt_gensalt_ra.3
+
+all: $(CRYPT_OBJS) man
+
+check: crypt_test
+ ./crypt_test
+
+crypt_test: $(TEST_OBJS)
+ $(LD) $(LDFLAGS) $(TEST_OBJS) -o $@
+
+crypt_test.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h
+ $(CC) -c $(CFLAGS) wrapper.c -DTEST -o $@
+
+check_threads: crypt_test_threads
+ ./crypt_test_threads
+
+crypt_test_threads: $(TEST_THREADS_OBJS)
+ $(LD) $(LDFLAGS) $(TEST_THREADS_OBJS) -lpthread -o $@
+
+crypt_test_threads.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h
+ $(CC) -c $(CFLAGS) wrapper.c -DTEST -DTEST_THREADS=4 -o $@
+
+man: $(EXTRA_MANS)
+
+$(EXTRA_MANS):
+ echo '.so man3/crypt.3' > $@
+
+crypt_blowfish.o: crypt_blowfish.h
+crypt_gensalt.o: crypt_gensalt.h
+wrapper.o: crypt.h ow-crypt.h crypt_blowfish.h crypt_gensalt.h
+
+.c.o:
+ $(CC) -c $(CFLAGS) $*.c
+
+.S.o:
+ $(AS) $(ASFLAGS) $*.S
+
+clean:
+ $(RM) crypt_test crypt_test_threads *.o $(EXTRA_MANS) core
diff --git a/src/auth/blowfish/PERFORMANCE b/src/auth/blowfish/PERFORMANCE
new file mode 100644
index 00000000..9d6fe4ef
--- /dev/null
+++ b/src/auth/blowfish/PERFORMANCE
@@ -0,0 +1,30 @@
+These numbers are for 32 iterations ("$2a$05"):
+
+ OpenBSD 3.0 bcrypt(*) crypt_blowfish 0.4.4
+Pentium III, 840 MHz 99 c/s 121 c/s (+22%)
+Alpha 21164PC, 533 MHz 55.5 c/s 76.9 c/s (+38%)
+UltraSparc IIi, 400 MHz 49.9 c/s 52.5 c/s (+5%)
+Pentium, 120 MHz 8.8 c/s 20.1 c/s (+128%)
+PA-RISC 7100LC, 80 MHz 8.5 c/s 16.3 c/s (+92%)
+
+(*) built with -fomit-frame-pointer -funroll-loops, which I don't
+think happens for libcrypt.
+
+Starting with version 1.1 released in June 2011, default builds of
+crypt_blowfish invoke a quick self-test on every hash computation.
+This has roughly a 4.8% performance impact at "$2a$05", but only a 0.6%
+impact at a more typical setting of "$2a$08".
+
+The large speedup for the original Pentium is due to the assembly
+code and the weird optimizations this processor requires.
+
+The numbers for password cracking are 2 to 10% higher than those for
+crypt_blowfish as certain things may be done out of the loop and the
+code doesn't need to be reentrant.
+
+Recent versions of John the Ripper (1.6.25-dev and newer) achieve an
+additional 15% speedup on the Pentium Pro family of processors (which
+includes Pentium III) with a separate version of the assembly code and
+run-time CPU detection.
+
+$Owl: Owl/packages/glibc/crypt_blowfish/PERFORMANCE,v 1.6 2011/06/21 12:09:20 solar Exp $
diff --git a/src/auth/blowfish/README b/src/auth/blowfish/README
new file mode 100644
index 00000000..e95da230
--- /dev/null
+++ b/src/auth/blowfish/README
@@ -0,0 +1,68 @@
+This is an implementation of a password hashing method, provided via the
+crypt(3) and a reentrant interface. It is fully compatible with
+OpenBSD's bcrypt.c for prefix "$2b$", originally by Niels Provos and
+David Mazieres. (Please refer to the included crypt(3) man page for
+information on minor compatibility issues for other bcrypt prefixes.)
+
+I've placed this code in the public domain, with fallback to a
+permissive license. Please see the comment in crypt_blowfish.c for
+more information.
+
+You can use the provided routines in your own packages, or link them
+into a C library. I've provided hooks for linking into GNU libc, but
+it shouldn't be too hard to get this into another C library. Note
+that simply adding this code into your libc is probably not enough to
+make your system use the new password hashing algorithm. Changes to
+passwd(1), PAM modules, or whatever else your system uses will likely
+be needed as well. These are not a part of this package, but see
+LINKS for a pointer to our tcb suite.
+
+Instructions on using the routines in one of the two common ways are
+given below. It is recommended that you test the routines on your
+system before you start. Type "make check" or "make check_threads"
+(if you have the POSIX threads library), then "make clean".
+
+
+1. Using the routines in your programs.
+
+The available interfaces are in ow-crypt.h, and this is the file you
+should include. You won't need crypt.h. When linking, add all of the
+C files and x86.S (you can compile and link it even on a non-x86, it
+will produce no code in this case).
+
+
+2. Building the routines into GNU C library.
+
+For versions 2.13 and 2.14 (and likely other nearby ones), extract the
+library sources as usual. Apply the patch for glibc 2.14 provided in
+this package. Enter crypt/ and rename crypt.h to gnu-crypt.h within
+that directory. Copy the C sources, header, and assembly (x86.S) files
+from this package in there as well (but be sure you don't overwrite the
+Makefile). Configure, build, and install the library as usual.
+
+For versions 2.2 to 2.3.6 (and likely also for some newer ones),
+extract the library sources and maybe its optional add-ons as usual.
+Apply the patch for glibc 2.3.6 provided in this package. Enter
+crypt/ and rename crypt.h to gnu-crypt.h within that directory. Copy
+the C sources, header, and assembly (x86.S) files from this package in
+there as well (but be sure you don't overwrite the Makefile).
+Configure, build, and install the library as usual.
+
+For versions 2.1 to 2.1.3, extract the library sources and the crypt
+and linuxthreads add-ons as usual. Apply the patch for glibc 2.1.3
+provided in this package. Enter crypt/sysdeps/unix/, and rename
+crypt.h to gnu-crypt.h within that directory. Copy C sources, header,
+and assembly (x86.S) files from this package in there as well (but be
+sure you don't overwrite the Makefile). Configure, build, and install
+the library as usual.
+
+Programs that want to use the provided interfaces will need to include
+crypt.h (but not ow-crypt.h directly). By default, prototypes for the
+new routines aren't defined (but the extra functionality of crypt(3)
+is indeed available). You need to define _OW_SOURCE to obtain the new
+routines as well.
+
+--
+Solar Designer
+
+$Owl: Owl/packages/glibc/crypt_blowfish/README,v 1.10 2014/07/07 15:19:04 solar Exp $
diff --git a/src/auth/blowfish/crypt.3 b/src/auth/blowfish/crypt.3
new file mode 100644
index 00000000..b4c08954
--- /dev/null
+++ b/src/auth/blowfish/crypt.3
@@ -0,0 +1,575 @@
+.\" Written and revised by Solar Designer in 2000-2011.
+.\" No copyright is claimed, and this man page is hereby placed in the public
+.\" domain. In case this attempt to disclaim copyright and place the man page
+.\" in the public domain is deemed null and void, then the man page is
+.\" Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
+.\" general public under the following terms:
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted.
+.\"
+.\" There's ABSOLUTELY NO WARRANTY, express or implied.
+.\"
+.\" This manual page in its current form is intended for use on systems
+.\" based on the GNU C Library with crypt_blowfish patched into libcrypt.
+.\"
+.TH CRYPT 3 "July 7, 2014" "Openwall Project" "Library functions"
+.ad l
+.\" No macros in NAME to keep makewhatis happy.
+.SH NAME
+\fBcrypt\fR, \fBcrypt_r\fR, \fBcrypt_rn\fR, \fBcrypt_ra\fR,
+\fBcrypt_gensalt\fR, \fBcrypt_gensalt_rn\fR, \fBcrypt_gensalt_ra\fR
+\- password hashing
+.SH SYNOPSIS
+.B #define _XOPEN_SOURCE
+.br
+.B #include
+.sp
+.in +8
+.ti -8
+.BI "char *crypt(const char *" key ", const char *" setting );
+.in -8
+.sp
+.B #define _GNU_SOURCE
+.br
+.B #include
+.sp
+.in +8
+.ti -8
+.BI "char *crypt_r(const char *" key ", const char *" setting ", struct crypt_data *" data );
+.in -8
+.sp
+.B #define _OW_SOURCE
+.br
+.B #include
+.sp
+.in +8
+.ti -8
+.BI "char *crypt_rn(const char *" key ", const char *" setting ", void *" data ", int " size );
+.ti -8
+.BI "char *crypt_ra(const char *" key ", const char *" setting ", void **" data ", int *" size );
+.ti -8
+.BI "char *crypt_gensalt(const char *" prefix ", unsigned long " count ", const char *" input ", int " size );
+.ti -8
+.BI "char *crypt_gensalt_rn(const char *" prefix ", unsigned long " count ", const char *" input ", int " size ", char *" output ", int " output_size );
+.ti -8
+.BI "char *crypt_gensalt_ra(const char *" prefix ", unsigned long " count ", const char *" input ", int " size );
+.ad b
+.de crypt
+.BR crypt ,
+.BR crypt_r ,
+.BR crypt_rn ", \\$1"
+.ie "\\$2"" .B crypt_ra
+.el .BR crypt_ra "\\$2"
+..
+.de crypt_gensalt
+.BR crypt_gensalt ,
+.BR crypt_gensalt_rn ", \\$1"
+.ie "\\$2"" .B crypt_gensalt_ra
+.el .BR crypt_gensalt_ra "\\$2"
+..
+.SH DESCRIPTION
+The
+.crypt and
+functions calculate a cryptographic hash function of
+.I key
+with one of a number of supported methods as requested with
+.IR setting ,
+which is also used to pass a salt and possibly other parameters to
+the chosen method.
+The hashing methods are explained below.
+.PP
+Unlike
+.BR crypt ,
+the functions
+.BR crypt_r ,
+.BR crypt_rn " and"
+.B crypt_ra
+are reentrant.
+They place their result and possibly their private data in a
+.I data
+area of
+.I size
+bytes as passed to them by an application and/or in memory they
+allocate dynamically. Some hashing algorithms may use the data area to
+cache precomputed intermediate values across calls. Thus, applications
+must properly initialize the data area before its first use.
+.B crypt_r
+requires that only
+.I data->initialized
+be reset to zero;
+.BR crypt_rn " and " crypt_ra
+require that either the entire data area is zeroed or, in the case of
+.BR crypt_ra ,
+.I *data
+is NULL. When called with a NULL
+.I *data
+or insufficient
+.I *size
+for the requested hashing algorithm,
+.B crypt_ra
+uses
+.BR realloc (3)
+to allocate the required amount of memory dynamically. Thus,
+.B crypt_ra
+has the additional requirement that
+.IR *data ,
+when non-NULL, must point to an area allocated either with a previous
+call to
+.B crypt_ra
+or with a
+.BR malloc (3)
+family call.
+The memory allocated by
+.B crypt_ra
+should be freed with
+.BR free "(3)."
+.PP
+The
+.crypt_gensalt and
+functions compile a string for use as
+.I setting
+\- with the given
+.I prefix
+(used to choose a hashing method), the iteration
+.I count
+(if supported by the chosen method) and up to
+.I size
+cryptographically random
+.I input
+bytes for use as the actual salt.
+If
+.I count
+is 0, a low default will be picked.
+The random bytes may be obtained from
+.BR /dev/urandom .
+Unlike
+.BR crypt_gensalt ,
+the functions
+.BR crypt_gensalt_rn " and " crypt_gensalt_ra
+are reentrant.
+.B crypt_gensalt_rn
+places its result in the
+.I output
+buffer of
+.I output_size
+bytes.
+.B crypt_gensalt_ra
+allocates memory for its result dynamically. The memory should be
+freed with
+.BR free "(3)."
+.SH RETURN VALUE
+Upon successful completion, the functions
+.crypt and
+return a pointer to a string containing the setting that was actually used
+and a printable encoding of the hash function value.
+The entire string is directly usable as
+.I setting
+with other calls to
+.crypt and
+and as
+.I prefix
+with calls to
+.crypt_gensalt and .
+.PP
+The behavior of
+.B crypt
+on errors isn't well standardized. Some implementations simply can't fail
+(unless the process dies, in which case they obviously can't return),
+others return NULL or a fixed string. Most implementations don't set
+.IR errno ,
+but some do. SUSv2 specifies only returning NULL and setting
+.I errno
+as a valid behavior, and defines only one possible error
+.RB "(" ENOSYS ,
+"The functionality is not supported on this implementation.")
+Unfortunately, most existing applications aren't prepared to handle
+NULL returns from
+.BR crypt .
+The description below corresponds to this implementation of
+.BR crypt " and " crypt_r
+only, and to
+.BR crypt_rn " and " crypt_ra .
+The behavior may change to match standards, other implementations or
+existing applications.
+.PP
+.BR crypt " and " crypt_r
+may only fail (and return) when passed an invalid or unsupported
+.IR setting ,
+in which case they return a pointer to a magic string that is
+shorter than 13 characters and is guaranteed to differ from
+.IR setting .
+This behavior is safe for older applications which assume that
+.B crypt
+can't fail, when both setting new passwords and authenticating against
+existing password hashes.
+.BR crypt_rn " and " crypt_ra
+return NULL to indicate failure. All four functions set
+.I errno
+when they fail.
+.PP
+The functions
+.crypt_gensalt and
+return a pointer to the compiled string for
+.IR setting ,
+or NULL on error in which case
+.I errno
+is set.
+.SH ERRORS
+.TP
+.B EINVAL
+.crypt "" :
+.I setting
+is invalid or not supported by this implementation;
+.sp
+.crypt_gensalt "" :
+.I prefix
+is invalid or not supported by this implementation;
+.I count
+is invalid for the requested
+.IR prefix ;
+the input
+.I size
+is insufficient for the smallest valid salt with the requested
+.IR prefix ;
+.I input
+is NULL.
+.TP
+.B ERANGE
+.BR crypt_rn :
+the provided data area
+.I size
+is insufficient for the requested hashing algorithm;
+.sp
+.BR crypt_gensalt_rn :
+.I output_size
+is too small to hold the compiled
+.I setting
+string.
+.TP
+.B ENOMEM
+.B crypt
+(original glibc only):
+failed to allocate memory for the output buffer (which subsequent calls
+would re-use);
+.sp
+.BR crypt_ra :
+.I *data
+is NULL or
+.I *size
+is insufficient for the requested hashing algorithm and
+.BR realloc (3)
+failed;
+.sp
+.BR crypt_gensalt_ra :
+failed to allocate memory for the compiled
+.I setting
+string.
+.TP
+.B ENOSYS
+.B crypt
+(SUSv2):
+the functionality is not supported on this implementation;
+.sp
+.BR crypt ,
+.B crypt_r
+(glibc 2.0 to 2.0.1 only):
+.de no-crypt-add-on
+the crypt add-on is not compiled in and
+.I setting
+requests something other than the MD5-based algorithm.
+..
+.no-crypt-add-on
+.TP
+.B EOPNOTSUPP
+.BR crypt ,
+.B crypt_r
+(glibc 2.0.2 to 2.1.3 only):
+.no-crypt-add-on
+.SH HASHING METHODS
+The implemented hashing methods are intended specifically for processing
+user passwords for storage and authentication;
+they are at best inefficient for most other purposes.
+.PP
+It is important to understand that password hashing is not a replacement
+for strong passwords.
+It is always possible for an attacker with access to password hashes
+to try guessing candidate passwords against the hashes.
+There are, however, certain properties a password hashing method may have
+which make these key search attacks somewhat harder.
+.PP
+All of the hashing methods use salts such that the same
+.I key
+may produce many possible hashes.
+Proper use of salts may defeat a number of attacks, including:
+.TP
+1.
+The ability to try candidate passwords against multiple hashes at the
+price of one.
+.TP
+2.
+The use of pre-hashed lists of candidate passwords.
+.TP
+3.
+The ability to determine whether two users (or two accounts of one user)
+have the same or different passwords without actually having to guess
+one of the passwords.
+.PP
+The key search attacks depend on computing hashes of large numbers of
+candidate passwords.
+Thus, the computational cost of a good password hashing method must be
+high \- but of course not too high to render it impractical.
+.PP
+All hashing methods implemented within the
+.crypt and
+interfaces use multiple iterations of an underlying cryptographic
+primitive specifically in order to increase the cost of trying a
+candidate password.
+Unfortunately, due to hardware improvements, the hashing methods which
+have a fixed cost become increasingly less secure over time.
+.PP
+In addition to salts, modern password hashing methods accept a variable
+iteration
+.IR count .
+This makes it possible to adapt their cost to the hardware improvements
+while still maintaining compatibility.
+.PP
+The following hashing methods are or may be implemented within the
+described interfaces:
+.PP
+.de hash
+.ad l
+.TP
+.I prefix
+.ie "\\$1"" \{\
+"" (empty string);
+.br
+a string matching ^[./0-9A-Za-z]{2} (see
+.BR regex (7))
+.\}
+.el "\\$1"
+.TP
+.B Encoding syntax
+\\$2
+.TP
+.B Maximum password length
+\\$3 (uses \\$4-bit characters)
+.TP
+.B Effective key size
+.ie "\\$5"" limited by the hash size only
+.el up to \\$5 bits
+.TP
+.B Hash size
+\\$6 bits
+.TP
+.B Salt size
+\\$7 bits
+.TP
+.B Iteration count
+\\$8
+.ad b
+..
+.ti -2
+.B Traditional DES-based
+.br
+This method is supported by almost all implementations of
+.BR crypt .
+Unfortunately, it no longer offers adequate security because of its many
+limitations.
+Thus, it should not be used for new passwords unless you absolutely have
+to be able to migrate the password hashes to other systems.
+.hash "" "[./0-9A-Za-z]{13}" 8 7 56 64 12 25
+.PP
+.ti -2
+.B Extended BSDI-style DES-based
+.br
+This method is used on BSDI and is also available on at least NetBSD,
+OpenBSD, and FreeBSD due to the use of David Burren's FreeSec library.
+.hash _ "_[./0-9A-Za-z]{19}" unlimited 7 56 64 24 "1 to 2**24-1 (must be odd)"
+.PP
+.ti -2
+.B FreeBSD-style MD5-based
+.br
+This is Poul-Henning Kamp's MD5-based password hashing method originally
+developed for FreeBSD.
+It is currently supported on many free Unix-like systems, on Solaris 10
+and newer, and it is part of the official glibc.
+Its main disadvantage is the fixed iteration count, which is already
+too low for the currently available hardware.
+.hash "$1$" "\e$1\e$[^$]{1,8}\e$[./0-9A-Za-z]{22}" unlimited 8 "" 128 "6 to 48" 1000
+.PP
+.ti -2
+.BR "OpenBSD-style Blowfish-based" " (" bcrypt )
+.br
+.B bcrypt
+was originally developed by Niels Provos and David Mazieres for OpenBSD
+and is also supported on recent versions of FreeBSD and NetBSD,
+on Solaris 10 and newer, and on several GNU/*/Linux distributions.
+It is, however, not part of the official glibc.
+.PP
+While both
+.B bcrypt
+and the BSDI-style DES-based hashing offer a variable iteration count,
+.B bcrypt
+may scale to even faster hardware, doesn't allow for certain optimizations
+specific to password cracking only, doesn't have the effective key size
+limitation, and uses 8-bit characters in passwords.
+.hash "$2b$" "\e$2[abxy]\e$[0-9]{2}\e$[./A-Za-z0-9]{53}" 72 8 "" 184 128 "2**4 to 2**99 (current implementations are limited to 2**31 iterations)"
+.PP
+With
+.BR bcrypt ,
+the
+.I count
+passed to
+.crypt_gensalt and
+is the base-2 logarithm of the actual iteration count.
+.PP
+.B bcrypt
+hashes used the "$2a$" prefix since 1997.
+However, in 2011 an implementation bug was discovered in crypt_blowfish
+(versions up to 1.0.4 inclusive) affecting handling of password characters with
+the 8th bit set.
+Besides fixing the bug,
+to provide for upgrade strategies for existing systems, two new prefixes were
+introduced: "$2x$", which fully re-introduces the bug, and "$2y$", which
+guarantees correct handling of both 7- and 8-bit characters.
+OpenBSD 5.5 introduced the "$2b$" prefix for behavior that exactly matches
+crypt_blowfish's "$2y$", and current crypt_blowfish supports it as well.
+Unfortunately, the behavior of "$2a$" on password characters with the 8th bit
+set has to be considered system-specific.
+When generating new password hashes, the "$2b$" or "$2y$" prefix should be used.
+(If such hashes ever need to be migrated to a system that does not yet support
+these new prefixes, the prefix in migrated copies of the already-generated
+hashes may be changed to "$2a$".)
+.PP
+.crypt_gensalt and
+support the "$2b$", "$2y$", and "$2a$" prefixes (the latter for legacy programs
+or configurations), but not "$2x$" (which must not be used for new hashes).
+.crypt and
+support all four of these prefixes.
+.SH PORTABILITY NOTES
+Programs using any of these functions on a glibc 2.x system must be
+linked against
+.BR libcrypt .
+However, many Unix-like operating systems and older versions of the
+GNU C Library include the
+.BR crypt " function in " libc .
+.PP
+The
+.BR crypt_r ,
+.BR crypt_rn ,
+.BR crypt_ra ,
+.crypt_gensalt and
+functions are very non-portable.
+.PP
+The set of supported hashing methods is implementation-dependent.
+.SH CONFORMING TO
+The
+.B crypt
+function conforms to SVID, X/OPEN, and is available on BSD 4.3.
+The strings returned by
+.B crypt
+are not required to be portable among conformant systems.
+.PP
+.B crypt_r
+is a GNU extension.
+There's also a
+.B crypt_r
+function on HP-UX and MKS Toolkit, but the prototypes and semantics differ.
+.PP
+.B crypt_gensalt
+is an Openwall extension.
+There's also a
+.B crypt_gensalt
+function on Solaris 10 and newer, but the prototypes and semantics differ.
+.PP
+.BR crypt_rn ,
+.BR crypt_ra ,
+.BR crypt_gensalt_rn ,
+and
+.B crypt_gensalt_ra
+are Openwall extensions.
+.SH HISTORY
+A rotor-based
+.B crypt
+function appeared in Version 6 AT&T UNIX.
+The "traditional"
+.B crypt
+first appeared in Version 7 AT&T UNIX.
+.PP
+The
+.B crypt_r
+function was introduced during glibc 2.0 development.
+.SH BUGS
+The return values of
+.BR crypt " and " crypt_gensalt
+point to static buffers that are overwritten by subsequent calls.
+These functions are not thread-safe.
+.RB ( crypt
+on recent versions of Solaris uses thread-specific data and actually is
+thread-safe.)
+.PP
+The strings returned by certain other implementations of
+.B crypt
+on error may be stored in read-only locations or only initialized once,
+which makes it unsafe to always attempt to zero out the buffer normally
+pointed to by the
+.B crypt
+return value as it would otherwise be preferable for security reasons.
+The problem could be avoided with the use of
+.BR crypt_r ,
+.BR crypt_rn ,
+or
+.B crypt_ra
+where the application has full control over output buffers of these functions
+(and often over some of their private data as well).
+Unfortunately, the functions aren't (yet?) available on platforms where
+.B crypt
+has this undesired property.
+.PP
+Applications using the thread-safe
+.B crypt_r
+need to allocate address space for the large (over 128 KB)
+.I struct crypt_data
+structure. Each thread needs a separate instance of the structure. The
+.B crypt_r
+interface makes it impossible to implement a hashing algorithm which
+would need to keep an even larger amount of private data, without breaking
+binary compatibility.
+.B crypt_ra
+allows for dynamically increasing the allocation size as required by the
+hashing algorithm that is actually used. Unfortunately,
+.B crypt_ra
+is even more non-portable than
+.BR crypt_r .
+.PP
+Multi-threaded applications or library functions which are meant to be
+thread-safe should use
+.BR crypt_gensalt_rn " or " crypt_gensalt_ra
+rather than
+.BR crypt_gensalt .
+.SH SEE ALSO
+.BR login (1),
+.BR passwd (1),
+.BR crypto (3),
+.BR encrypt (3),
+.BR free (3),
+.BR getpass (3),
+.BR getpwent (3),
+.BR malloc (3),
+.BR realloc (3),
+.BR shadow (3),
+.BR passwd (5),
+.BR shadow (5),
+.BR regex (7),
+.BR pam (8)
+.sp
+Niels Provos and David Mazieres. A Future-Adaptable Password Scheme.
+Proceedings of the 1999 USENIX Annual Technical Conference, June 1999.
+.br
+http://www.usenix.org/events/usenix99/provos.html
+.sp
+Robert Morris and Ken Thompson. Password Security: A Case History.
+Unix Seventh Edition Manual, Volume 2, April 1978.
+.br
+http://plan9.bell-labs.com/7thEdMan/vol2/password
diff --git a/src/auth/blowfish/crypt.h b/src/auth/blowfish/crypt.h
new file mode 100644
index 00000000..12e67055
--- /dev/null
+++ b/src/auth/blowfish/crypt.h
@@ -0,0 +1,24 @@
+/*
+ * Written by Solar Designer in 2000-2002.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 2000-2002 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ */
+
+#include
+
+#if defined(_OW_SOURCE) || defined(__USE_OW)
+#define __SKIP_GNU
+#undef __SKIP_OW
+#include
+#undef __SKIP_GNU
+#endif
diff --git a/src/auth/blowfish/crypt_blowfish.c b/src/auth/blowfish/crypt_blowfish.c
new file mode 100644
index 00000000..9d3f3be8
--- /dev/null
+++ b/src/auth/blowfish/crypt_blowfish.c
@@ -0,0 +1,907 @@
+/*
+ * The crypt_blowfish homepage is:
+ *
+ * http://www.openwall.com/crypt/
+ *
+ * This code comes from John the Ripper password cracker, with reentrant
+ * and crypt(3) interfaces added, but optimizations specific to password
+ * cracking removed.
+ *
+ * Written by Solar Designer in 1998-2014.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 1998-2014 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * It is my intent that you should be able to use this on your system,
+ * as part of a software package, or anywhere else to improve security,
+ * ensure compatibility, or for any other purpose. I would appreciate
+ * it if you give credit where it is due and keep your modifications in
+ * the public domain as well, but I don't require that in order to let
+ * you place this code and any modifications you make under a license
+ * of your choice.
+ *
+ * This implementation is fully compatible with OpenBSD's bcrypt.c for prefix
+ * "$2b$", originally by Niels Provos , and it uses
+ * some of his ideas. The password hashing algorithm was designed by David
+ * Mazieres . For information on the level of
+ * compatibility for bcrypt hash prefixes other than "$2b$", please refer to
+ * the comments in BF_set_key() below and to the included crypt(3) man page.
+ *
+ * There's a paper on the algorithm that explains its design decisions:
+ *
+ * http://www.usenix.org/events/usenix99/provos.html
+ *
+ * Some of the tricks in BF_ROUND might be inspired by Eric Young's
+ * Blowfish library (I can't be sure if I would think of something if I
+ * hadn't seen his code).
+ */
+
+#include
+
+#include
+#ifndef __set_errno
+#define __set_errno(val) errno = (val)
+#endif
+
+/* Just to make sure the prototypes match the actual definitions */
+#include "crypt_blowfish.h"
+
+#ifdef __i386__
+#define BF_ASM 1
+#define BF_SCALE 1
+#elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__)
+#define BF_ASM 0
+#define BF_SCALE 1
+#else
+#define BF_ASM 0
+#define BF_SCALE 0
+#endif
+
+typedef unsigned int BF_word;
+typedef signed int BF_word_signed;
+
+/* Number of Blowfish rounds, this is also hardcoded into a few places */
+#define BF_N 16
+
+typedef BF_word BF_key[BF_N + 2];
+
+typedef struct {
+ BF_word S[4][0x100];
+ BF_key P;
+} BF_ctx;
+
+/*
+ * Magic IV for 64 Blowfish encryptions that we do at the end.
+ * The string is "OrpheanBeholderScryDoubt" on big-endian.
+ */
+static BF_word BF_magic_w[6] = {
+ 0x4F727068, 0x65616E42, 0x65686F6C,
+ 0x64657253, 0x63727944, 0x6F756274
+};
+
+/*
+ * P-box and S-box tables initialized with digits of Pi.
+ */
+static BF_ctx BF_init_state = {
+ {
+ {
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+ 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+ 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+ 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+ 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+ 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+ 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+ 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+ 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+ 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+ 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
+ }, {
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+ 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+ 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+ 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+ 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+ 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+ 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+ 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+ 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+ 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+ 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+ 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+ 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+ 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+ 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+ 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+ 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+ 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+ 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+ 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+ 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+ 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
+ }, {
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+ 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+ 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+ 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+ 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+ 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+ 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+ 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+ 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+ 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+ 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+ 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+ 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+ 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+ 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+ 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+ 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+ 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+ 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+ 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
+ }, {
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+ 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+ 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+ 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+ 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+ 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+ 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+ 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+ 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+ 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+ 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+ 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+ 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+ 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+ 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+ 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+ 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+ 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+ 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+ 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+ }
+ }, {
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+ 0x9216d5d9, 0x8979fb1b
+ }
+};
+
+static unsigned char BF_itoa64[64 + 1] =
+ "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+static unsigned char BF_atoi64[0x60] = {
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
+ 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
+ 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
+};
+
+#define BF_safe_atoi64(dst, src) \
+{ \
+ tmp = (unsigned char)(src); \
+ if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
+ tmp = BF_atoi64[tmp]; \
+ if (tmp > 63) return -1; \
+ (dst) = tmp; \
+}
+
+static int BF_decode(BF_word *dst, const char *src, int size)
+{
+ unsigned char *dptr = (unsigned char *)dst;
+ unsigned char *end = dptr + size;
+ const unsigned char *sptr = (const unsigned char *)src;
+ unsigned int tmp, c1, c2, c3, c4;
+
+ do {
+ BF_safe_atoi64(c1, *sptr++);
+ BF_safe_atoi64(c2, *sptr++);
+ *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
+ if (dptr >= end) break;
+
+ BF_safe_atoi64(c3, *sptr++);
+ *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
+ if (dptr >= end) break;
+
+ BF_safe_atoi64(c4, *sptr++);
+ *dptr++ = ((c3 & 0x03) << 6) | c4;
+ } while (dptr < end);
+
+ return 0;
+}
+
+static void BF_encode(char *dst, const BF_word *src, int size)
+{
+ const unsigned char *sptr = (const unsigned char *)src;
+ const unsigned char *end = sptr + size;
+ unsigned char *dptr = (unsigned char *)dst;
+ unsigned int c1, c2;
+
+ do {
+ c1 = *sptr++;
+ *dptr++ = BF_itoa64[c1 >> 2];
+ c1 = (c1 & 0x03) << 4;
+ if (sptr >= end) {
+ *dptr++ = BF_itoa64[c1];
+ break;
+ }
+
+ c2 = *sptr++;
+ c1 |= c2 >> 4;
+ *dptr++ = BF_itoa64[c1];
+ c1 = (c2 & 0x0f) << 2;
+ if (sptr >= end) {
+ *dptr++ = BF_itoa64[c1];
+ break;
+ }
+
+ c2 = *sptr++;
+ c1 |= c2 >> 6;
+ *dptr++ = BF_itoa64[c1];
+ *dptr++ = BF_itoa64[c2 & 0x3f];
+ } while (sptr < end);
+}
+
+static void BF_swap(BF_word *x, int count)
+{
+ static int endianness_check = 1;
+ char *is_little_endian = (char *)&endianness_check;
+ BF_word tmp;
+
+ if (*is_little_endian)
+ do {
+ tmp = *x;
+ tmp = (tmp << 16) | (tmp >> 16);
+ *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
+ } while (--count);
+}
+
+#if BF_SCALE
+/* Architectures which can shift addresses left by 2 bits with no extra cost */
+#define BF_ROUND(L, R, N) \
+ tmp1 = L & 0xFF; \
+ tmp2 = L >> 8; \
+ tmp2 &= 0xFF; \
+ tmp3 = L >> 16; \
+ tmp3 &= 0xFF; \
+ tmp4 = L >> 24; \
+ tmp1 = data.ctx.S[3][tmp1]; \
+ tmp2 = data.ctx.S[2][tmp2]; \
+ tmp3 = data.ctx.S[1][tmp3]; \
+ tmp3 += data.ctx.S[0][tmp4]; \
+ tmp3 ^= tmp2; \
+ R ^= data.ctx.P[N + 1]; \
+ tmp3 += tmp1; \
+ R ^= tmp3;
+#else
+/* Architectures with no complicated addressing modes supported */
+#define BF_INDEX(S, i) \
+ (*((BF_word *)(((unsigned char *)S) + (i))))
+#define BF_ROUND(L, R, N) \
+ tmp1 = L & 0xFF; \
+ tmp1 <<= 2; \
+ tmp2 = L >> 6; \
+ tmp2 &= 0x3FC; \
+ tmp3 = L >> 14; \
+ tmp3 &= 0x3FC; \
+ tmp4 = L >> 22; \
+ tmp4 &= 0x3FC; \
+ tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
+ tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
+ tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
+ tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
+ tmp3 ^= tmp2; \
+ R ^= data.ctx.P[N + 1]; \
+ tmp3 += tmp1; \
+ R ^= tmp3;
+#endif
+
+/*
+ * Encrypt one block, BF_N is hardcoded here.
+ */
+#define BF_ENCRYPT \
+ L ^= data.ctx.P[0]; \
+ BF_ROUND(L, R, 0); \
+ BF_ROUND(R, L, 1); \
+ BF_ROUND(L, R, 2); \
+ BF_ROUND(R, L, 3); \
+ BF_ROUND(L, R, 4); \
+ BF_ROUND(R, L, 5); \
+ BF_ROUND(L, R, 6); \
+ BF_ROUND(R, L, 7); \
+ BF_ROUND(L, R, 8); \
+ BF_ROUND(R, L, 9); \
+ BF_ROUND(L, R, 10); \
+ BF_ROUND(R, L, 11); \
+ BF_ROUND(L, R, 12); \
+ BF_ROUND(R, L, 13); \
+ BF_ROUND(L, R, 14); \
+ BF_ROUND(R, L, 15); \
+ tmp4 = R; \
+ R = L; \
+ L = tmp4 ^ data.ctx.P[BF_N + 1];
+
+#if BF_ASM
+#define BF_body() \
+ _BF_body_r(&data.ctx);
+#else
+#define BF_body() \
+ L = R = 0; \
+ ptr = data.ctx.P; \
+ do { \
+ ptr += 2; \
+ BF_ENCRYPT; \
+ *(ptr - 2) = L; \
+ *(ptr - 1) = R; \
+ } while (ptr < &data.ctx.P[BF_N + 2]); \
+\
+ ptr = data.ctx.S[0]; \
+ do { \
+ ptr += 2; \
+ BF_ENCRYPT; \
+ *(ptr - 2) = L; \
+ *(ptr - 1) = R; \
+ } while (ptr < &data.ctx.S[3][0xFF]);
+#endif
+
+static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
+ unsigned char flags)
+{
+ const char *ptr = key;
+ unsigned int bug, i, j;
+ BF_word safety, sign, diff, tmp[2];
+
+/*
+ * There was a sign extension bug in older revisions of this function. While
+ * we would have liked to simply fix the bug and move on, we have to provide
+ * a backwards compatibility feature (essentially the bug) for some systems and
+ * a safety measure for some others. The latter is needed because for certain
+ * multiple inputs to the buggy algorithm there exist easily found inputs to
+ * the correct algorithm that produce the same hash. Thus, we optionally
+ * deviate from the correct algorithm just enough to avoid such collisions.
+ * While the bug itself affected the majority of passwords containing
+ * characters with the 8th bit set (although only a percentage of those in a
+ * collision-producing way), the anti-collision safety measure affects
+ * only a subset of passwords containing the '\xff' character (not even all of
+ * those passwords, just some of them). This character is not found in valid
+ * UTF-8 sequences and is rarely used in popular 8-bit character encodings.
+ * Thus, the safety measure is unlikely to cause much annoyance, and is a
+ * reasonable tradeoff to use when authenticating against existing hashes that
+ * are not reliably known to have been computed with the correct algorithm.
+ *
+ * We use an approach that tries to minimize side-channel leaks of password
+ * information - that is, we mostly use fixed-cost bitwise operations instead
+ * of branches or table lookups. (One conditional branch based on password
+ * length remains. It is not part of the bug aftermath, though, and is
+ * difficult and possibly unreasonable to avoid given the use of C strings by
+ * the caller, which results in similar timing leaks anyway.)
+ *
+ * For actual implementation, we set an array index in the variable "bug"
+ * (0 means no bug, 1 means sign extension bug emulation) and a flag in the
+ * variable "safety" (bit 16 is set when the safety measure is requested).
+ * Valid combinations of settings are:
+ *
+ * Prefix "$2a$": bug = 0, safety = 0x10000
+ * Prefix "$2b$": bug = 0, safety = 0
+ * Prefix "$2x$": bug = 1, safety = 0
+ * Prefix "$2y$": bug = 0, safety = 0
+ */
+ bug = (unsigned int)flags & 1;
+ safety = ((BF_word)flags & 2) << 15;
+
+ sign = diff = 0;
+
+ for (i = 0; i < BF_N + 2; i++) {
+ tmp[0] = tmp[1] = 0;
+ for (j = 0; j < 4; j++) {
+ tmp[0] <<= 8;
+ tmp[0] |= (unsigned char)*ptr; /* correct */
+ tmp[1] <<= 8;
+ tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
+/*
+ * Sign extension in the first char has no effect - nothing to overwrite yet,
+ * and those extra 24 bits will be fully shifted out of the 32-bit word. For
+ * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
+ * extension in tmp[1] occurs. Once this flag is set, it remains set.
+ */
+ if (j)
+ sign |= tmp[1] & 0x80;
+ if (!*ptr)
+ ptr = key;
+ else
+ ptr++;
+ }
+ diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
+
+ expanded[i] = tmp[bug];
+ initial[i] = BF_init_state.P[i] ^ tmp[bug];
+ }
+
+/*
+ * At this point, "diff" is zero iff the correct and buggy algorithms produced
+ * exactly the same result. If so and if "sign" is non-zero, which indicates
+ * that there was a non-benign sign extension, this means that we have a
+ * collision between the correctly computed hash for this password and a set of
+ * passwords that could be supplied to the buggy algorithm. Our safety measure
+ * is meant to protect from such many-buggy to one-correct collisions, by
+ * deviating from the correct algorithm in such cases. Let's check for this.
+ */
+ diff |= diff >> 16; /* still zero iff exact match */
+ diff &= 0xffff; /* ditto */
+ diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
+ sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
+ sign &= ~diff & safety; /* action needed? */
+
+/*
+ * If we have determined that we need to deviate from the correct algorithm,
+ * flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but
+ * let's stick to it now. It came out of the approach we used above, and it's
+ * not any worse than any other choice we could make.)
+ *
+ * It is crucial that we don't do the same to the expanded key used in the main
+ * Eksblowfish loop. By doing it to only one of these two, we deviate from a
+ * state that could be directly specified by a password to the buggy algorithm
+ * (and to the fully correct one as well, but that's a side-effect).
+ */
+ initial[0] ^= sign;
+}
+
+static const unsigned char flags_by_subtype[26] =
+ {2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
+
+static char *BF_crypt(const char *key, const char *setting,
+ char *output, int size,
+ BF_word min)
+{
+#if BF_ASM
+ extern void _BF_body_r(BF_ctx *ctx);
+#endif
+ struct {
+ BF_ctx ctx;
+ BF_key expanded_key;
+ union {
+ BF_word salt[4];
+ BF_word output[6];
+ } binary;
+ } data;
+ BF_word L, R;
+ BF_word tmp1, tmp2, tmp3, tmp4;
+ BF_word *ptr;
+ BF_word count;
+ int i;
+
+ if (size < 7 + 22 + 31 + 1) {
+ __set_errno(ERANGE);
+ return NULL;
+ }
+
+ if (setting[0] != '$' ||
+ setting[1] != '2' ||
+ setting[2] < 'a' || setting[2] > 'z' ||
+ !flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
+ setting[3] != '$' ||
+ setting[4] < '0' || setting[4] > '3' ||
+ setting[5] < '0' || setting[5] > '9' ||
+ (setting[4] == '3' && setting[5] > '1') ||
+ setting[6] != '$') {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
+ if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+ BF_swap(data.binary.salt, 4);
+
+ BF_set_key(key, data.expanded_key, data.ctx.P,
+ flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']);
+
+ memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
+
+ L = R = 0;
+ for (i = 0; i < BF_N + 2; i += 2) {
+ L ^= data.binary.salt[i & 2];
+ R ^= data.binary.salt[(i & 2) + 1];
+ BF_ENCRYPT;
+ data.ctx.P[i] = L;
+ data.ctx.P[i + 1] = R;
+ }
+
+ ptr = data.ctx.S[0];
+ do {
+ ptr += 4;
+ L ^= data.binary.salt[(BF_N + 2) & 3];
+ R ^= data.binary.salt[(BF_N + 3) & 3];
+ BF_ENCRYPT;
+ *(ptr - 4) = L;
+ *(ptr - 3) = R;
+
+ L ^= data.binary.salt[(BF_N + 4) & 3];
+ R ^= data.binary.salt[(BF_N + 5) & 3];
+ BF_ENCRYPT;
+ *(ptr - 2) = L;
+ *(ptr - 1) = R;
+ } while (ptr < &data.ctx.S[3][0xFF]);
+
+ do {
+ int done;
+
+ for (i = 0; i < BF_N + 2; i += 2) {
+ data.ctx.P[i] ^= data.expanded_key[i];
+ data.ctx.P[i + 1] ^= data.expanded_key[i + 1];
+ }
+
+ done = 0;
+ do {
+ BF_body();
+ if (done)
+ break;
+ done = 1;
+
+ tmp1 = data.binary.salt[0];
+ tmp2 = data.binary.salt[1];
+ tmp3 = data.binary.salt[2];
+ tmp4 = data.binary.salt[3];
+ for (i = 0; i < BF_N; i += 4) {
+ data.ctx.P[i] ^= tmp1;
+ data.ctx.P[i + 1] ^= tmp2;
+ data.ctx.P[i + 2] ^= tmp3;
+ data.ctx.P[i + 3] ^= tmp4;
+ }
+ data.ctx.P[16] ^= tmp1;
+ data.ctx.P[17] ^= tmp2;
+ } while (1);
+ } while (--count);
+
+ for (i = 0; i < 6; i += 2) {
+ L = BF_magic_w[i];
+ R = BF_magic_w[i + 1];
+
+ count = 64;
+ do {
+ BF_ENCRYPT;
+ } while (--count);
+
+ data.binary.output[i] = L;
+ data.binary.output[i + 1] = R;
+ }
+
+ memcpy(output, setting, 7 + 22 - 1);
+ output[7 + 22 - 1] = BF_itoa64[(int)
+ BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
+
+/* This has to be bug-compatible with the original implementation, so
+ * only encode 23 of the 24 bytes. :-) */
+ BF_swap(data.binary.output, 6);
+ BF_encode(&output[7 + 22], data.binary.output, 23);
+ output[7 + 22 + 31] = '\0';
+
+ return output;
+}
+
+int _crypt_output_magic(const char *setting, char *output, int size)
+{
+ if (size < 3)
+ return -1;
+
+ output[0] = '*';
+ output[1] = '0';
+ output[2] = '\0';
+
+ if (setting[0] == '*' && setting[1] == '0')
+ output[1] = '1';
+
+ return 0;
+}
+
+/*
+ * Please preserve the runtime self-test. It serves two purposes at once:
+ *
+ * 1. We really can't afford the risk of producing incompatible hashes e.g.
+ * when there's something like gcc bug 26587 again, whereas an application or
+ * library integrating this code might not also integrate our external tests or
+ * it might not run them after every build. Even if it does, the miscompile
+ * might only occur on the production build, but not on a testing build (such
+ * as because of different optimization settings). It is painful to recover
+ * from incorrectly-computed hashes - merely fixing whatever broke is not
+ * enough. Thus, a proactive measure like this self-test is needed.
+ *
+ * 2. We don't want to leave sensitive data from our actual password hash
+ * computation on the stack or in registers. Previous revisions of the code
+ * would do explicit cleanups, but simply running the self-test after hash
+ * computation is more reliable.
+ *
+ * The performance cost of this quick self-test is around 0.6% at the "$2a$08"
+ * setting.
+ */
+char *_crypt_blowfish_rn(const char *key, const char *setting,
+ char *output, int size)
+{
+ const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
+ const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu";
+ static const char * const test_hashes[2] =
+ {"i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */
+ "VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55"}; /* 'x' */
+ const char *test_hash = test_hashes[0];
+ char *retval;
+ const char *p;
+ int save_errno, ok;
+ struct {
+ char s[7 + 22 + 1];
+ char o[7 + 22 + 31 + 1 + 1 + 1];
+ } buf;
+
+/* Hash the supplied password */
+ _crypt_output_magic(setting, output, size);
+ retval = BF_crypt(key, setting, output, size, 16);
+ save_errno = errno;
+
+/*
+ * Do a quick self-test. It is important that we make both calls to BF_crypt()
+ * from the same scope such that they likely use the same stack locations,
+ * which makes the second call overwrite the first call's sensitive data on the
+ * stack and makes it more likely that any alignment related issues would be
+ * detected by the self-test.
+ */
+ memcpy(buf.s, test_setting, sizeof(buf.s));
+ if (retval) {
+ unsigned int flags = flags_by_subtype[
+ (unsigned int)(unsigned char)setting[2] - 'a'];
+ test_hash = test_hashes[flags & 1];
+ buf.s[2] = setting[2];
+ }
+ memset(buf.o, 0x55, sizeof(buf.o));
+ buf.o[sizeof(buf.o) - 1] = 0;
+ p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1);
+
+ ok = (p == buf.o &&
+ !memcmp(p, buf.s, 7 + 22) &&
+ !memcmp(p + (7 + 22), test_hash, 31 + 1 + 1 + 1));
+
+ {
+ const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345";
+ BF_key ae, ai, ye, yi;
+ BF_set_key(k, ae, ai, 2); /* $2a$ */
+ BF_set_key(k, ye, yi, 4); /* $2y$ */
+ ai[0] ^= 0x10000; /* undo the safety (for comparison) */
+ ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 &&
+ !memcmp(ae, ye, sizeof(ae)) &&
+ !memcmp(ai, yi, sizeof(ai));
+ }
+
+ __set_errno(save_errno);
+ if (ok)
+ return retval;
+
+/* Should not happen */
+ _crypt_output_magic(setting, output, size);
+ __set_errno(EINVAL); /* pretend we don't support this hash type */
+ return NULL;
+}
+
+char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
+ const char *input, int size, char *output, int output_size)
+{
+ if (size < 16 || output_size < 7 + 22 + 1 ||
+ (count && (count < 4 || count > 31)) ||
+ prefix[0] != '$' || prefix[1] != '2' ||
+ (prefix[2] != 'a' && prefix[2] != 'b' && prefix[2] != 'y')) {
+ if (output_size > 0) output[0] = '\0';
+ __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
+ return NULL;
+ }
+
+ if (!count) count = 5;
+
+ output[0] = '$';
+ output[1] = '2';
+ output[2] = prefix[2];
+ output[3] = '$';
+ output[4] = '0' + count / 10;
+ output[5] = '0' + count % 10;
+ output[6] = '$';
+
+ BF_encode(&output[7], (const BF_word *)input, 16);
+ output[7 + 22] = '\0';
+
+ return output;
+}
diff --git a/src/auth/blowfish/crypt_blowfish.h b/src/auth/blowfish/crypt_blowfish.h
new file mode 100644
index 00000000..2ee0d8c1
--- /dev/null
+++ b/src/auth/blowfish/crypt_blowfish.h
@@ -0,0 +1,27 @@
+/*
+ * Written by Solar Designer in 2000-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ */
+
+#ifndef _CRYPT_BLOWFISH_H
+#define _CRYPT_BLOWFISH_H
+
+extern int _crypt_output_magic(const char *setting, char *output, int size);
+extern char *_crypt_blowfish_rn(const char *key, const char *setting,
+ char *output, int size);
+extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
+ unsigned long count,
+ const char *input, int size, char *output, int output_size);
+
+#endif
diff --git a/src/auth/blowfish/crypt_gensalt.c b/src/auth/blowfish/crypt_gensalt.c
new file mode 100644
index 00000000..73c15a1a
--- /dev/null
+++ b/src/auth/blowfish/crypt_gensalt.c
@@ -0,0 +1,124 @@
+/*
+ * Written by Solar Designer in 2000-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ *
+ * This file contains salt generation functions for the traditional and
+ * other common crypt(3) algorithms, except for bcrypt which is defined
+ * entirely in crypt_blowfish.c.
+ */
+
+#include
+
+#include
+#ifndef __set_errno
+#define __set_errno(val) errno = (val)
+#endif
+
+/* Just to make sure the prototypes match the actual definitions */
+#include "crypt_gensalt.h"
+
+unsigned char _crypt_itoa64[64 + 1] =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+char *_crypt_gensalt_traditional_rn(const char *prefix, unsigned long count,
+ const char *input, int size, char *output, int output_size)
+{
+ (void) prefix;
+
+ if (size < 2 || output_size < 2 + 1 || (count && count != 25)) {
+ if (output_size > 0) output[0] = '\0';
+ __set_errno((output_size < 2 + 1) ? ERANGE : EINVAL);
+ return NULL;
+ }
+
+ output[0] = _crypt_itoa64[(unsigned int)input[0] & 0x3f];
+ output[1] = _crypt_itoa64[(unsigned int)input[1] & 0x3f];
+ output[2] = '\0';
+
+ return output;
+}
+
+char *_crypt_gensalt_extended_rn(const char *prefix, unsigned long count,
+ const char *input, int size, char *output, int output_size)
+{
+ unsigned long value;
+
+ (void) prefix;
+
+/* Even iteration counts make it easier to detect weak DES keys from a look
+ * at the hash, so they should be avoided */
+ if (size < 3 || output_size < 1 + 4 + 4 + 1 ||
+ (count && (count > 0xffffff || !(count & 1)))) {
+ if (output_size > 0) output[0] = '\0';
+ __set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL);
+ return NULL;
+ }
+
+ if (!count) count = 725;
+
+ output[0] = '_';
+ output[1] = _crypt_itoa64[count & 0x3f];
+ output[2] = _crypt_itoa64[(count >> 6) & 0x3f];
+ output[3] = _crypt_itoa64[(count >> 12) & 0x3f];
+ output[4] = _crypt_itoa64[(count >> 18) & 0x3f];
+ value = (unsigned long)(unsigned char)input[0] |
+ ((unsigned long)(unsigned char)input[1] << 8) |
+ ((unsigned long)(unsigned char)input[2] << 16);
+ output[5] = _crypt_itoa64[value & 0x3f];
+ output[6] = _crypt_itoa64[(value >> 6) & 0x3f];
+ output[7] = _crypt_itoa64[(value >> 12) & 0x3f];
+ output[8] = _crypt_itoa64[(value >> 18) & 0x3f];
+ output[9] = '\0';
+
+ return output;
+}
+
+char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count,
+ const char *input, int size, char *output, int output_size)
+{
+ unsigned long value;
+
+ (void) prefix;
+
+ if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000)) {
+ if (output_size > 0) output[0] = '\0';
+ __set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL);
+ return NULL;
+ }
+
+ output[0] = '$';
+ output[1] = '1';
+ output[2] = '$';
+ value = (unsigned long)(unsigned char)input[0] |
+ ((unsigned long)(unsigned char)input[1] << 8) |
+ ((unsigned long)(unsigned char)input[2] << 16);
+ output[3] = _crypt_itoa64[value & 0x3f];
+ output[4] = _crypt_itoa64[(value >> 6) & 0x3f];
+ output[5] = _crypt_itoa64[(value >> 12) & 0x3f];
+ output[6] = _crypt_itoa64[(value >> 18) & 0x3f];
+ output[7] = '\0';
+
+ if (size >= 6 && output_size >= 3 + 4 + 4 + 1) {
+ value = (unsigned long)(unsigned char)input[3] |
+ ((unsigned long)(unsigned char)input[4] << 8) |
+ ((unsigned long)(unsigned char)input[5] << 16);
+ output[7] = _crypt_itoa64[value & 0x3f];
+ output[8] = _crypt_itoa64[(value >> 6) & 0x3f];
+ output[9] = _crypt_itoa64[(value >> 12) & 0x3f];
+ output[10] = _crypt_itoa64[(value >> 18) & 0x3f];
+ output[11] = '\0';
+ }
+
+ return output;
+}
diff --git a/src/auth/blowfish/crypt_gensalt.h b/src/auth/blowfish/crypt_gensalt.h
new file mode 100644
index 00000000..457bbfe2
--- /dev/null
+++ b/src/auth/blowfish/crypt_gensalt.h
@@ -0,0 +1,30 @@
+/*
+ * Written by Solar Designer in 2000-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ */
+
+#ifndef _CRYPT_GENSALT_H
+#define _CRYPT_GENSALT_H
+
+extern unsigned char _crypt_itoa64[];
+extern char *_crypt_gensalt_traditional_rn(const char *prefix,
+ unsigned long count,
+ const char *input, int size, char *output, int output_size);
+extern char *_crypt_gensalt_extended_rn(const char *prefix,
+ unsigned long count,
+ const char *input, int size, char *output, int output_size);
+extern char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count,
+ const char *input, int size, char *output, int output_size);
+
+#endif
diff --git a/src/auth/blowfish/glibc-2.1.3-crypt.diff b/src/auth/blowfish/glibc-2.1.3-crypt.diff
new file mode 100644
index 00000000..415e5b44
--- /dev/null
+++ b/src/auth/blowfish/glibc-2.1.3-crypt.diff
@@ -0,0 +1,53 @@
+--- glibc-2.1.3.orig/crypt/sysdeps/unix/Makefile 1997-03-05 00:33:59 +0000
++++ glibc-2.1.3/crypt/sysdeps/unix/Makefile 2000-06-11 03:13:41 +0000
+@@ -1,4 +1,4 @@
+ ifeq ($(subdir),md5-crypt)
+-libcrypt-routines += crypt crypt_util
+-dont_distribute += crypt.c crypt_util.c
++libcrypt-routines += crypt crypt_util crypt_blowfish x86 crypt_gensalt wrapper
++dont_distribute += crypt.c crypt_util.c crypt_blowfish.c x86.S crypt_gensalt.c wrapper.c
+ endif
+--- glibc-2.1.3.orig/crypt/sysdeps/unix/crypt-entry.c 1998-12-10 12:49:04 +0000
++++ glibc-2.1.3/crypt/sysdeps/unix/crypt-entry.c 2000-06-11 03:14:57 +0000
+@@ -70,7 +70,7 @@ extern struct crypt_data _ufc_foobar;
+ */
+
+ char *
+-__crypt_r (key, salt, data)
++__des_crypt_r (key, salt, data)
+ const char *key;
+ const char *salt;
+ struct crypt_data * __restrict data;
+@@ -115,6 +115,7 @@ __crypt_r (key, salt, data)
+ _ufc_output_conversion_r (res[0], res[1], salt, data);
+ return data->crypt_3_buf;
+ }
++#if 0
+ weak_alias (__crypt_r, crypt_r)
+
+ char *
+@@ -147,3 +148,4 @@ __fcrypt (key, salt)
+ return crypt (key, salt);
+ }
+ #endif
++#endif
+--- glibc-2.1.3.orig/md5-crypt/Makefile 1998-07-02 22:46:47 +0000
++++ glibc-2.1.3/md5-crypt/Makefile 2000-06-11 03:12:34 +0000
+@@ -21,7 +21,7 @@
+ #
+ subdir := md5-crypt
+
+-headers := crypt.h
++headers := crypt.h gnu-crypt.h ow-crypt.h
+
+ distribute := md5.h
+
+--- glibc-2.1.3.orig/md5-crypt/Versions 1998-07-02 22:32:07 +0000
++++ glibc-2.1.3/md5-crypt/Versions 2000-06-11 09:11:03 +0000
+@@ -1,5 +1,6 @@
+ libcrypt {
+ GLIBC_2.0 {
+ crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
++ crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra;
+ }
+ }
diff --git a/src/auth/blowfish/glibc-2.14-crypt.diff b/src/auth/blowfish/glibc-2.14-crypt.diff
new file mode 100644
index 00000000..bacd12ed
--- /dev/null
+++ b/src/auth/blowfish/glibc-2.14-crypt.diff
@@ -0,0 +1,55 @@
+diff -urp glibc-2.14.orig/crypt/Makefile glibc-2.14/crypt/Makefile
+--- glibc-2.14.orig/crypt/Makefile 2011-05-31 04:12:33 +0000
++++ glibc-2.14/crypt/Makefile 2011-07-16 21:40:56 +0000
+@@ -22,6 +22,7 @@
+ subdir := crypt
+
+ headers := crypt.h
++headers += gnu-crypt.h ow-crypt.h
+
+ extra-libs := libcrypt
+ extra-libs-others := $(extra-libs)
+@@ -29,6 +30,8 @@ extra-libs-others := $(extra-libs)
+ libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
+ crypt_util
+
++libcrypt-routines += crypt_blowfish x86 crypt_gensalt wrapper
++
+ tests := cert md5c-test sha256c-test sha512c-test
+
+ distribute := ufc-crypt.h crypt-private.h ufc.c speeds.c README.ufc-crypt \
+diff -urp glibc-2.14.orig/crypt/Versions glibc-2.14/crypt/Versions
+--- glibc-2.14.orig/crypt/Versions 2011-05-31 04:12:33 +0000
++++ glibc-2.14/crypt/Versions 2011-07-16 21:40:56 +0000
+@@ -1,5 +1,6 @@
+ libcrypt {
+ GLIBC_2.0 {
+ crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
++ crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra;
+ }
+ }
+diff -urp glibc-2.14.orig/crypt/crypt-entry.c glibc-2.14/crypt/crypt-entry.c
+--- glibc-2.14.orig/crypt/crypt-entry.c 2011-05-31 04:12:33 +0000
++++ glibc-2.14/crypt/crypt-entry.c 2011-07-16 21:40:56 +0000
+@@ -82,7 +82,7 @@ extern struct crypt_data _ufc_foobar;
+ */
+
+ char *
+-__crypt_r (key, salt, data)
++__des_crypt_r (key, salt, data)
+ const char *key;
+ const char *salt;
+ struct crypt_data * __restrict data;
+@@ -137,6 +137,7 @@ __crypt_r (key, salt, data)
+ _ufc_output_conversion_r (res[0], res[1], salt, data);
+ return data->crypt_3_buf;
+ }
++#if 0
+ weak_alias (__crypt_r, crypt_r)
+
+ char *
+@@ -177,3 +178,4 @@ __fcrypt (key, salt)
+ return crypt (key, salt);
+ }
+ #endif
++#endif
diff --git a/src/auth/blowfish/glibc-2.3.6-crypt.diff b/src/auth/blowfish/glibc-2.3.6-crypt.diff
new file mode 100644
index 00000000..4471054b
--- /dev/null
+++ b/src/auth/blowfish/glibc-2.3.6-crypt.diff
@@ -0,0 +1,52 @@
+--- glibc-2.3.6.orig/crypt/Makefile 2001-07-06 04:54:45 +0000
++++ glibc-2.3.6/crypt/Makefile 2004-02-27 00:23:48 +0000
+@@ -21,14 +21,14 @@
+ #
+ subdir := crypt
+
+-headers := crypt.h
++headers := crypt.h gnu-crypt.h ow-crypt.h
+
+ distribute := md5.h
+
+ extra-libs := libcrypt
+ extra-libs-others := $(extra-libs)
+
+-libcrypt-routines := crypt-entry md5-crypt md5 crypt crypt_util
++libcrypt-routines := crypt-entry md5-crypt md5 crypt crypt_util crypt_blowfish x86 crypt_gensalt wrapper
+
+ tests = cert md5test md5c-test
+
+--- glibc-2.3.6.orig/crypt/Versions 2000-03-04 00:47:30 +0000
++++ glibc-2.3.6/crypt/Versions 2004-02-27 00:25:15 +0000
+@@ -1,5 +1,6 @@
+ libcrypt {
+ GLIBC_2.0 {
+ crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
++ crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra;
+ }
+ }
+--- glibc-2.3.6.orig/crypt/crypt-entry.c 2001-07-06 05:18:49 +0000
++++ glibc-2.3.6/crypt/crypt-entry.c 2004-02-27 00:12:32 +0000
+@@ -70,7 +70,7 @@ extern struct crypt_data _ufc_foobar;
+ */
+
+ char *
+-__crypt_r (key, salt, data)
++__des_crypt_r (key, salt, data)
+ const char *key;
+ const char *salt;
+ struct crypt_data * __restrict data;
+@@ -115,6 +115,7 @@ __crypt_r (key, salt, data)
+ _ufc_output_conversion_r (res[0], res[1], salt, data);
+ return data->crypt_3_buf;
+ }
++#if 0
+ weak_alias (__crypt_r, crypt_r)
+
+ char *
+@@ -147,3 +148,4 @@ __fcrypt (key, salt)
+ return crypt (key, salt);
+ }
+ #endif
++#endif
diff --git a/src/auth/blowfish/ow-crypt.h b/src/auth/blowfish/ow-crypt.h
new file mode 100644
index 00000000..2e487942
--- /dev/null
+++ b/src/auth/blowfish/ow-crypt.h
@@ -0,0 +1,43 @@
+/*
+ * Written by Solar Designer in 2000-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ */
+
+#ifndef _OW_CRYPT_H
+#define _OW_CRYPT_H
+
+#ifndef __GNUC__
+#undef __const
+#define __const const
+#endif
+
+#ifndef __SKIP_GNU
+extern char *crypt(__const char *key, __const char *setting);
+extern char *crypt_r(__const char *key, __const char *setting, void *data);
+#endif
+
+#ifndef __SKIP_OW
+extern char *crypt_rn(__const char *key, __const char *setting,
+ void *data, int size);
+extern char *crypt_ra(__const char *key, __const char *setting,
+ void **data, int *size);
+extern char *crypt_gensalt(__const char *prefix, unsigned long count,
+ __const char *input, int size);
+extern char *crypt_gensalt_rn(__const char *prefix, unsigned long count,
+ __const char *input, int size, char *output, int output_size);
+extern char *crypt_gensalt_ra(__const char *prefix, unsigned long count,
+ __const char *input, int size);
+#endif
+
+#endif
diff --git a/src/auth/blowfish/wrapper.c b/src/auth/blowfish/wrapper.c
new file mode 100644
index 00000000..1e49c90d
--- /dev/null
+++ b/src/auth/blowfish/wrapper.c
@@ -0,0 +1,551 @@
+/*
+ * Written by Solar Designer in 2000-2014.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 2000-2014 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ */
+
+#include
+#include
+
+#include
+#ifndef __set_errno
+#define __set_errno(val) errno = (val)
+#endif
+
+#ifdef TEST
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef TEST_THREADS
+#include
+#endif
+#endif
+
+#define CRYPT_OUTPUT_SIZE (7 + 22 + 31 + 1)
+#define CRYPT_GENSALT_OUTPUT_SIZE (7 + 22 + 1)
+
+#if defined(__GLIBC__) && defined(_LIBC)
+#define __SKIP_GNU
+#endif
+#include "ow-crypt.h"
+
+#include "crypt_blowfish.h"
+#include "crypt_gensalt.h"
+
+#if defined(__GLIBC__) && defined(_LIBC)
+/* crypt.h from glibc-crypt-2.1 will define struct crypt_data for us */
+#include "crypt.h"
+extern char *__md5_crypt_r(const char *key, const char *salt,
+ char *buffer, int buflen);
+/* crypt-entry.c needs to be patched to define __des_crypt_r rather than
+ * __crypt_r, and not define crypt_r and crypt at all */
+extern char *__des_crypt_r(const char *key, const char *salt,
+ struct crypt_data *data);
+extern struct crypt_data _ufc_foobar;
+#endif
+
+static int _crypt_data_alloc(void **data, int *size, int need)
+{
+ void *updated;
+
+ if (*data && *size >= need) return 0;
+
+ updated = realloc(*data, need);
+
+ if (!updated) {
+#ifndef __GLIBC__
+ /* realloc(3) on glibc sets errno, so we don't need to bother */
+ __set_errno(ENOMEM);
+#endif
+ return -1;
+ }
+
+#if defined(__GLIBC__) && defined(_LIBC)
+ if (need >= sizeof(struct crypt_data))
+ ((struct crypt_data *)updated)->initialized = 0;
+#endif
+
+ *data = updated;
+ *size = need;
+
+ return 0;
+}
+
+static char *_crypt_retval_magic(char *retval, const char *setting,
+ char *output, int size)
+{
+ if (retval)
+ return retval;
+
+ if (_crypt_output_magic(setting, output, size))
+ return NULL; /* shouldn't happen */
+
+ return output;
+}
+
+#if defined(__GLIBC__) && defined(_LIBC)
+/*
+ * Applications may re-use the same instance of struct crypt_data without
+ * resetting the initialized field in order to let crypt_r() skip some of
+ * its initialization code. Thus, it is important that our multiple hashing
+ * algorithms either don't conflict with each other in their use of the
+ * data area or reset the initialized field themselves whenever required.
+ * Currently, the hashing algorithms simply have no conflicts: the first
+ * field of struct crypt_data is the 128-byte large DES key schedule which
+ * __des_crypt_r() calculates each time it is called while the two other
+ * hashing algorithms use less than 128 bytes of the data area.
+ */
+
+char *__crypt_rn(__const char *key, __const char *setting,
+ void *data, int size)
+{
+ if (setting[0] == '$' && setting[1] == '2')
+ return _crypt_blowfish_rn(key, setting, (char *)data, size);
+ if (setting[0] == '$' && setting[1] == '1')
+ return __md5_crypt_r(key, setting, (char *)data, size);
+ if (setting[0] == '$' || setting[0] == '_') {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+ if (size >= sizeof(struct crypt_data))
+ return __des_crypt_r(key, setting, (struct crypt_data *)data);
+ __set_errno(ERANGE);
+ return NULL;
+}
+
+char *__crypt_ra(__const char *key, __const char *setting,
+ void **data, int *size)
+{
+ if (setting[0] == '$' && setting[1] == '2') {
+ if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE))
+ return NULL;
+ return _crypt_blowfish_rn(key, setting, (char *)*data, *size);
+ }
+ if (setting[0] == '$' && setting[1] == '1') {
+ if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE))
+ return NULL;
+ return __md5_crypt_r(key, setting, (char *)*data, *size);
+ }
+ if (setting[0] == '$' || setting[0] == '_') {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+ if (_crypt_data_alloc(data, size, sizeof(struct crypt_data)))
+ return NULL;
+ return __des_crypt_r(key, setting, (struct crypt_data *)*data);
+}
+
+char *__crypt_r(__const char *key, __const char *setting,
+ struct crypt_data *data)
+{
+ return _crypt_retval_magic(
+ __crypt_rn(key, setting, data, sizeof(*data)),
+ setting, (char *)data, sizeof(*data));
+}
+
+char *__crypt(__const char *key, __const char *setting)
+{
+ return _crypt_retval_magic(
+ __crypt_rn(key, setting, &_ufc_foobar, sizeof(_ufc_foobar)),
+ setting, (char *)&_ufc_foobar, sizeof(_ufc_foobar));
+}
+#else
+char *crypt_rn(const char *key, const char *setting, void *data, int size)
+{
+ return _crypt_blowfish_rn(key, setting, (char *)data, size);
+}
+
+char *crypt_ra(const char *key, const char *setting,
+ void **data, int *size)
+{
+ if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE))
+ return NULL;
+ return _crypt_blowfish_rn(key, setting, (char *)*data, *size);
+}
+
+char *crypt_r(const char *key, const char *setting, void *data)
+{
+ return _crypt_retval_magic(
+ crypt_rn(key, setting, data, CRYPT_OUTPUT_SIZE),
+ setting, (char *)data, CRYPT_OUTPUT_SIZE);
+}
+
+char *crypt(const char *key, const char *setting)
+{
+ static char output[CRYPT_OUTPUT_SIZE];
+
+ return _crypt_retval_magic(
+ crypt_rn(key, setting, output, sizeof(output)),
+ setting, output, sizeof(output));
+}
+
+#define __crypt_gensalt_rn crypt_gensalt_rn
+#define __crypt_gensalt_ra crypt_gensalt_ra
+#define __crypt_gensalt crypt_gensalt
+#endif
+
+char *__crypt_gensalt_rn(const char *prefix, unsigned long count,
+ const char *input, int size, char *output, int output_size)
+{
+ char *(*use)(const char *_prefix, unsigned long _count,
+ const char *_input, int _size,
+ char *_output, int _output_size);
+
+ /* This may be supported on some platforms in the future */
+ if (!input) {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ if (!strncmp(prefix, "$2a$", 4) || !strncmp(prefix, "$2b$", 4) ||
+ !strncmp(prefix, "$2y$", 4))
+ use = _crypt_gensalt_blowfish_rn;
+ else
+ if (!strncmp(prefix, "$1$", 3))
+ use = _crypt_gensalt_md5_rn;
+ else
+ if (prefix[0] == '_')
+ use = _crypt_gensalt_extended_rn;
+ else
+ if (!prefix[0] ||
+ (prefix[0] && prefix[1] &&
+ memchr(_crypt_itoa64, prefix[0], 64) &&
+ memchr(_crypt_itoa64, prefix[1], 64)))
+ use = _crypt_gensalt_traditional_rn;
+ else {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ return use(prefix, count, input, size, output, output_size);
+}
+
+char *__crypt_gensalt_ra(const char *prefix, unsigned long count,
+ const char *input, int size)
+{
+ char output[CRYPT_GENSALT_OUTPUT_SIZE];
+ char *retval;
+
+ retval = __crypt_gensalt_rn(prefix, count,
+ input, size, output, sizeof(output));
+
+ if (retval) {
+ retval = strdup(retval);
+#ifndef __GLIBC__
+ /* strdup(3) on glibc sets errno, so we don't need to bother */
+ if (!retval)
+ __set_errno(ENOMEM);
+#endif
+ }
+
+ return retval;
+}
+
+char *__crypt_gensalt(const char *prefix, unsigned long count,
+ const char *input, int size)
+{
+ static char output[CRYPT_GENSALT_OUTPUT_SIZE];
+
+ return __crypt_gensalt_rn(prefix, count,
+ input, size, output, sizeof(output));
+}
+
+#if defined(__GLIBC__) && defined(_LIBC)
+weak_alias(__crypt_rn, crypt_rn)
+weak_alias(__crypt_ra, crypt_ra)
+weak_alias(__crypt_r, crypt_r)
+weak_alias(__crypt, crypt)
+weak_alias(__crypt_gensalt_rn, crypt_gensalt_rn)
+weak_alias(__crypt_gensalt_ra, crypt_gensalt_ra)
+weak_alias(__crypt_gensalt, crypt_gensalt)
+weak_alias(crypt, fcrypt)
+#endif
+
+#ifdef TEST
+static const char *tests[][3] = {
+ {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW",
+ "U*U"},
+ {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK",
+ "U*U*"},
+ {"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a",
+ "U*U*U"},
+ {"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui",
+ "0123456789abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ "chars after 72 are ignored"},
+ {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
+ "\xa3"},
+ {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
+ "\xff\xff\xa3"},
+ {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
+ "\xff\xff\xa3"},
+ {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nqd1wy.pTMdcvrRWxyiGL2eMz.2a85.",
+ "\xff\xff\xa3"},
+ {"$2b$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
+ "\xff\xff\xa3"},
+ {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq",
+ "\xa3"},
+ {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq",
+ "\xa3"},
+ {"$2b$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq",
+ "\xa3"},
+ {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi",
+ "1\xa3" "345"},
+ {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi",
+ "\xff\xa3" "345"},
+ {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi",
+ "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"},
+ {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi",
+ "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"},
+ {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.ZC1JEJ8Z4gPfpe1JOr/oyPXTWl9EFd.",
+ "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"},
+ {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e",
+ "\xff\xa3" "345"},
+ {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e",
+ "\xff\xa3" "345"},
+ {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS",
+ "\xa3" "ab"},
+ {"$2x$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS",
+ "\xa3" "ab"},
+ {"$2y$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS",
+ "\xa3" "ab"},
+ {"$2x$05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcAS",
+ "\xd1\x91"},
+ {"$2x$05$6bNw2HLQYeqHYyBfLMsv/O9LIGgn8OMzuDoHfof8AQimSGfcSWxnS",
+ "\xd0\xc1\xd2\xcf\xcc\xd8"},
+ {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6",
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "chars after 72 are ignored as usual"},
+ {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy",
+ "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
+ "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
+ "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
+ "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
+ "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
+ "\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"},
+ {"$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe",
+ "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
+ "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
+ "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
+ "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
+ "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
+ "\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"},
+ {"$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy",
+ ""},
+ {"*0", "", "$2a$03$CCCCCCCCCCCCCCCCCCCCC."},
+ {"*0", "", "$2a$32$CCCCCCCCCCCCCCCCCCCCC."},
+ {"*0", "", "$2c$05$CCCCCCCCCCCCCCCCCCCCC."},
+ {"*0", "", "$2z$05$CCCCCCCCCCCCCCCCCCCCC."},
+ {"*0", "", "$2`$05$CCCCCCCCCCCCCCCCCCCCC."},
+ {"*0", "", "$2{$05$CCCCCCCCCCCCCCCCCCCCC."},
+ {"*1", "", "*0"},
+ {NULL}
+};
+
+#define which tests[0]
+
+static volatile sig_atomic_t running;
+
+static void handle_timer(int signum)
+{
+ (void) signum;
+ running = 0;
+}
+
+static void *run(void *arg)
+{
+ unsigned long count = 0;
+ int i = 0;
+ void *data = NULL;
+ int size = 0x12345678;
+
+ do {
+ const char *hash = tests[i][0];
+ const char *key = tests[i][1];
+ const char *setting = tests[i][2];
+
+ if (!tests[++i][0])
+ i = 0;
+
+ if (setting && strlen(hash) < 30) /* not for benchmark */
+ continue;
+
+ if (strcmp(crypt_ra(key, hash, &data, &size), hash)) {
+ printf("%d: FAILED (crypt_ra/%d/%lu)\n",
+ (int)((char *)arg - (char *)0), i, count);
+ free(data);
+ return NULL;
+ }
+ count++;
+ } while (running);
+
+ free(data);
+ return count + (char *)0;
+}
+
+int main(void)
+{
+ struct itimerval it;
+ struct tms buf;
+ clock_t clk_tck, start_real, start_virtual, end_real, end_virtual;
+ unsigned long count;
+ void *data;
+ int size;
+ char *setting1, *setting2;
+ int i;
+#ifdef TEST_THREADS
+ pthread_t t[TEST_THREADS];
+ void *t_retval;
+#endif
+
+ data = NULL;
+ size = 0x12345678;
+
+ for (i = 0; tests[i][0]; i++) {
+ const char *hash = tests[i][0];
+ const char *key = tests[i][1];
+ const char *setting = tests[i][2];
+ const char *p;
+ int ok = !setting || strlen(hash) >= 30;
+ int o_size;
+ char s_buf[30], o_buf[61];
+ if (!setting) {
+ memcpy(s_buf, hash, sizeof(s_buf) - 1);
+ s_buf[sizeof(s_buf) - 1] = 0;
+ setting = s_buf;
+ }
+
+ __set_errno(0);
+ p = crypt(key, setting);
+ if ((!ok && !errno) || strcmp(p, hash)) {
+ printf("FAILED (crypt/%d)\n", i);
+ return 1;
+ }
+
+ if (ok && strcmp(crypt(key, hash), hash)) {
+ printf("FAILED (crypt/%d)\n", i);
+ return 1;
+ }
+
+ for (o_size = -1; o_size <= (int)sizeof(o_buf); o_size++) {
+ int ok_n = ok && o_size == (int)sizeof(o_buf);
+ const char *x = "abc";
+ strcpy(o_buf, x);
+ if (o_size >= 3) {
+ x = "*0";
+ if (setting[0] == '*' && setting[1] == '0')
+ x = "*1";
+ }
+ __set_errno(0);
+ p = crypt_rn(key, setting, o_buf, o_size);
+ if ((ok_n && (!p || strcmp(p, hash))) ||
+ (!ok_n && (!errno || p || strcmp(o_buf, x)))) {
+ printf("FAILED (crypt_rn/%d)\n", i);
+ return 1;
+ }
+ }
+
+ __set_errno(0);
+ p = crypt_ra(key, setting, &data, &size);
+ if ((ok && (!p || strcmp(p, hash))) ||
+ (!ok && (!errno || p || strcmp((char *)data, hash)))) {
+ printf("FAILED (crypt_ra/%d)\n", i);
+ return 1;
+ }
+ }
+
+ setting1 = crypt_gensalt(which[0], 12, data, size);
+ if (!setting1 || strncmp(setting1, "$2a$12$", 7)) {
+ puts("FAILED (crypt_gensalt)\n");
+ return 1;
+ }
+
+ setting2 = crypt_gensalt_ra(setting1, 12, data, size);
+ if (strcmp(setting1, setting2)) {
+ puts("FAILED (crypt_gensalt_ra/1)\n");
+ return 1;
+ }
+
+ (*(char *)data)++;
+ setting1 = crypt_gensalt_ra(setting2, 12, data, size);
+ if (!strcmp(setting1, setting2)) {
+ puts("FAILED (crypt_gensalt_ra/2)\n");
+ return 1;
+ }
+
+ free(setting1);
+ free(setting2);
+ free(data);
+
+#if defined(_SC_CLK_TCK) || !defined(CLK_TCK)
+ clk_tck = sysconf(_SC_CLK_TCK);
+#else
+ clk_tck = CLK_TCK;
+#endif
+
+ running = 1;
+ signal(SIGALRM, handle_timer);
+
+ memset(&it, 0, sizeof(it));
+ it.it_value.tv_sec = 5;
+ setitimer(ITIMER_REAL, &it, NULL);
+
+ start_real = times(&buf);
+ start_virtual = buf.tms_utime + buf.tms_stime;
+
+ count = (char *)run((char *)0) - (char *)0;
+
+ end_real = times(&buf);
+ end_virtual = buf.tms_utime + buf.tms_stime;
+ if (end_virtual == start_virtual) end_virtual++;
+
+ printf("%.1f c/s real, %.1f c/s virtual\n",
+ (float)count * clk_tck / (end_real - start_real),
+ (float)count * clk_tck / (end_virtual - start_virtual));
+
+#ifdef TEST_THREADS
+ running = 1;
+ it.it_value.tv_sec = 60;
+ setitimer(ITIMER_REAL, &it, NULL);
+ start_real = times(&buf);
+
+ for (i = 0; i < TEST_THREADS; i++)
+ if (pthread_create(&t[i], NULL, run, i + (char *)0)) {
+ perror("pthread_create");
+ return 1;
+ }
+
+ for (i = 0; i < TEST_THREADS; i++) {
+ if (pthread_join(t[i], &t_retval)) {
+ perror("pthread_join");
+ continue;
+ }
+ if (!t_retval) continue;
+ count = (char *)t_retval - (char *)0;
+ end_real = times(&buf);
+ printf("%d: %.1f c/s real\n", i,
+ (float)count * clk_tck / (end_real - start_real));
+ }
+#endif
+
+ return 0;
+}
+#endif
diff --git a/src/auth/blowfish/x86.S b/src/auth/blowfish/x86.S
new file mode 100644
index 00000000..b0f1cd2e
--- /dev/null
+++ b/src/auth/blowfish/x86.S
@@ -0,0 +1,203 @@
+/*
+ * Written by Solar Designer in 1998-2010.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 1998-2010 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ */
+
+#ifdef __i386__
+
+#if defined(__OpenBSD__) && !defined(__ELF__)
+#define UNDERSCORES
+#define ALIGN_LOG
+#endif
+
+#if defined(__CYGWIN32__) || defined(__MINGW32__)
+#define UNDERSCORES
+#endif
+
+#ifdef __DJGPP__
+#define UNDERSCORES
+#define ALIGN_LOG
+#endif
+
+#ifdef UNDERSCORES
+#define _BF_body_r __BF_body_r
+#endif
+
+#ifdef ALIGN_LOG
+#define DO_ALIGN(log) .align (log)
+#elif defined(DUMBAS)
+#define DO_ALIGN(log) .align 1 << log
+#else
+#define DO_ALIGN(log) .align (1 << (log))
+#endif
+
+#define BF_FRAME 0x200
+#define ctx %esp
+
+#define BF_ptr (ctx)
+
+#define S(N, r) N+BF_FRAME(ctx,r,4)
+#ifdef DUMBAS
+#define P(N) 0x1000+N+N+N+N+BF_FRAME(ctx)
+#else
+#define P(N) 0x1000+4*N+BF_FRAME(ctx)
+#endif
+
+/*
+ * This version of the assembly code is optimized primarily for the original
+ * Intel Pentium but is also careful to avoid partial register stalls on the
+ * Pentium Pro family of processors (tested up to Pentium III Coppermine).
+ *
+ * It is possible to do 15% faster on the Pentium Pro family and probably on
+ * many non-Intel x86 processors, but, unfortunately, that would make things
+ * twice slower for the original Pentium.
+ *
+ * An additional 2% speedup may be achieved with non-reentrant code.
+ */
+
+#define L %esi
+#define R %edi
+#define tmp1 %eax
+#define tmp1_lo %al
+#define tmp2 %ecx
+#define tmp2_hi %ch
+#define tmp3 %edx
+#define tmp3_lo %dl
+#define tmp4 %ebx
+#define tmp4_hi %bh
+#define tmp5 %ebp
+
+.text
+
+#define BF_ROUND(L, R, N) \
+ xorl L,tmp2; \
+ xorl tmp1,tmp1; \
+ movl tmp2,L; \
+ shrl $16,tmp2; \
+ movl L,tmp4; \
+ movb tmp2_hi,tmp1_lo; \
+ andl $0xFF,tmp2; \
+ movb tmp4_hi,tmp3_lo; \
+ andl $0xFF,tmp4; \
+ movl S(0,tmp1),tmp1; \
+ movl S(0x400,tmp2),tmp5; \
+ addl tmp5,tmp1; \
+ movl S(0x800,tmp3),tmp5; \
+ xorl tmp5,tmp1; \
+ movl S(0xC00,tmp4),tmp5; \
+ addl tmp1,tmp5; \
+ movl 4+P(N),tmp2; \
+ xorl tmp5,R
+
+#define BF_ENCRYPT_START \
+ BF_ROUND(L, R, 0); \
+ BF_ROUND(R, L, 1); \
+ BF_ROUND(L, R, 2); \
+ BF_ROUND(R, L, 3); \
+ BF_ROUND(L, R, 4); \
+ BF_ROUND(R, L, 5); \
+ BF_ROUND(L, R, 6); \
+ BF_ROUND(R, L, 7); \
+ BF_ROUND(L, R, 8); \
+ BF_ROUND(R, L, 9); \
+ BF_ROUND(L, R, 10); \
+ BF_ROUND(R, L, 11); \
+ BF_ROUND(L, R, 12); \
+ BF_ROUND(R, L, 13); \
+ BF_ROUND(L, R, 14); \
+ BF_ROUND(R, L, 15); \
+ movl BF_ptr,tmp5; \
+ xorl L,tmp2; \
+ movl P(17),L
+
+#define BF_ENCRYPT_END \
+ xorl R,L; \
+ movl tmp2,R
+
+DO_ALIGN(5)
+.globl _BF_body_r
+_BF_body_r:
+ movl 4(%esp),%eax
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ subl $BF_FRAME-8,%eax
+ xorl L,L
+ cmpl %esp,%eax
+ ja BF_die
+ xchgl %eax,%esp
+ xorl R,R
+ pushl %eax
+ leal 0x1000+BF_FRAME-4(ctx),%eax
+ movl 0x1000+BF_FRAME-4(ctx),tmp2
+ pushl %eax
+ xorl tmp3,tmp3
+BF_loop_P:
+ BF_ENCRYPT_START
+ addl $8,tmp5
+ BF_ENCRYPT_END
+ leal 0x1000+18*4+BF_FRAME(ctx),tmp1
+ movl tmp5,BF_ptr
+ cmpl tmp5,tmp1
+ movl L,-8(tmp5)
+ movl R,-4(tmp5)
+ movl P(0),tmp2
+ ja BF_loop_P
+ leal BF_FRAME(ctx),tmp5
+ xorl tmp3,tmp3
+ movl tmp5,BF_ptr
+BF_loop_S:
+ BF_ENCRYPT_START
+ BF_ENCRYPT_END
+ movl P(0),tmp2
+ movl L,(tmp5)
+ movl R,4(tmp5)
+ BF_ENCRYPT_START
+ BF_ENCRYPT_END
+ movl P(0),tmp2
+ movl L,8(tmp5)
+ movl R,12(tmp5)
+ BF_ENCRYPT_START
+ BF_ENCRYPT_END
+ movl P(0),tmp2
+ movl L,16(tmp5)
+ movl R,20(tmp5)
+ BF_ENCRYPT_START
+ addl $32,tmp5
+ BF_ENCRYPT_END
+ leal 0x1000+BF_FRAME(ctx),tmp1
+ movl tmp5,BF_ptr
+ cmpl tmp5,tmp1
+ movl P(0),tmp2
+ movl L,-8(tmp5)
+ movl R,-4(tmp5)
+ ja BF_loop_S
+ movl 4(%esp),%esp
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+
+BF_die:
+/* Oops, need to re-compile with a larger BF_FRAME. */
+ hlt
+ jmp BF_die
+
+#endif
+
+#if defined(__ELF__) && defined(__linux__)
+.section .note.GNU-stack,"",@progbits
+#endif
From fea69f5a5ed7eb3b1e404d40aa5b49a1b22be160 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 30 Oct 2017 14:49:23 +0100
Subject: [PATCH 024/528] Connecting to CentralEGA and parsing the JSON
response
---
src/auth/Makefile | 2 +-
src/auth/auth.conf.sample | 3 +-
src/auth/cega.c | 85 ++++++++++++++++++++++++++-------------
src/auth/config.c | 7 ++++
src/auth/config.h | 2 +
5 files changed, 69 insertions(+), 30 deletions(-)
diff --git a/src/auth/Makefile b/src/auth/Makefile
index 72440ec8..4ad86e3f 100644
--- a/src/auth/Makefile
+++ b/src/auth/Makefile
@@ -12,7 +12,7 @@ CC=gcc
LD=ld
AS=gcc -c
CFLAGS=-Wall -Wstrict-prototypes -Werror -fPIC -O2 -I. -I$(shell pg_config --includedir)
-LIBS=-lpq -lpam -lcurl -ljson-c -L$(shell pg_config --libdir)
+LIBS=-lpq -lpam -lcurl -ljq -L$(shell pg_config --libdir)
LIBDIR=/usr/local/lib/ega
diff --git a/src/auth/auth.conf.sample b/src/auth/auth.conf.sample
index 82c70a82..1cb0fd1f 100644
--- a/src/auth/auth.conf.sample
+++ b/src/auth/auth.conf.sample
@@ -6,10 +6,11 @@ debug = ok_why_not
db_connection = host=ega_db port=5432 dbname=lega user=postgres password=CHANGE-ME-PLEASE connect_timeout=1 sslmode=disable
enable_rest = yes
-#rest_endpoint = https://ega.crg.eu/user/%s
rest_endpoint = http://central_ega/user/%s
rest_user = lega
rest_password = change_me
+rest_resp_passwd = .response.result[0].password
+rest_resp_pubkey = .response.result[0].public_key
##################
# NSS Queries
diff --git a/src/auth/cega.c b/src/auth/cega.c
index a3ab9eeb..668dc369 100644
--- a/src/auth/cega.c
+++ b/src/auth/cega.c
@@ -6,14 +6,13 @@
#include
#include
-#include
+#include
#include "debug.h"
#include "config.h"
#include "backend.h"
#define URL_SIZE 1024
-#define EXPIRATION_INTERVAL ""
struct curl_res_s {
char *body;
@@ -44,6 +43,32 @@ curl_callback (void *contents, size_t size, size_t nmemb, void *p) {
return realsize;
}
+static const char*
+get_from_json(jq_state *jq, const char* query, jv json){
+
+ const char* res = NULL;
+
+ D("Processing query: %s\n", query);
+
+ if (!jq_compile(jq, query)){ D("Invalid query"); return NULL; }
+
+ jq_start(jq, json, 0); // no flags
+ jv result = jq_next(jq);
+ if(jv_is_valid(result)){
+
+ if (jv_get_kind(result) == JV_KIND_STRING) {
+ res = jv_string_value(result);
+ D("Valid result: %s\n", res);
+ jv_free(result);
+ } else {
+ D("Valid result but not a string\n");
+ //jv_dump(result, 0);
+ jv_free(result);
+ }
+ }
+ return res;
+}
+
bool
fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop)
{
@@ -52,10 +77,15 @@ fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop
bool success = false;
char endpoint[URL_SIZE];
struct curl_res_s *cres = NULL;
- enum json_tokener_error jerr = json_tokener_success;
- json_object *pwdh = NULL, *pubkey = NULL, *expiration = NULL;
- json_object *json = NULL, *json_response = NULL, *json_result = NULL, *jobj = NULL;
char* endpoint_creds = NULL;
+ jv parsed_response;
+ jq_state* jq = NULL;
+ const char *pwd = NULL;
+ const char *pbk = NULL;
+
+ /* enum json_tokener_error jerr = json_tokener_success; */
+ /* json_object *pwdh = NULL, *pubkey = NULL; */
+ /* json_object *json = NULL, *json_response = NULL, *json_result = NULL, *jobj = NULL; */
D("contacting cega for user: %s\n", username);
@@ -71,7 +101,6 @@ fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop
cres = (struct curl_res_s*)malloc(sizeof(struct curl_res_s));
-
curl_easy_setopt(curl, CURLOPT_NOPROGRESS , 1L ); /* shut off the progress meter */
curl_easy_setopt(curl, CURLOPT_URL , endpoint );
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION , curl_callback );
@@ -81,52 +110,52 @@ fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop
curl_easy_setopt(curl, CURLOPT_HTTPAUTH , CURLAUTH_BASIC);
endpoint_creds = (char*)malloc(1 + strlen(options->rest_user) + strlen(options->rest_password));
sprintf(endpoint_creds, "%s:%s", options->rest_user, options->rest_password);
+ D("CEGA credentials: %s\n", endpoint_creds);
curl_easy_setopt(curl, CURLOPT_USERPWD , endpoint_creds);
/* curl_easy_setopt(curl, CURLOPT_SSLCERT , options->ssl_cert); */
/* curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE , "PEM" ); */
-#ifdef DEBUG
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
-#endif
+/* #ifdef DEBUG */
+/* curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); */
+/* curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); */
+/* #endif */
/* Perform the request, res will get the return code */
D("Connecting to %s\n", endpoint);
res = curl_easy_perform(curl);
+ D("CEGA Request done\n");
if(res != CURLE_OK){
D("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
goto BAIL_OUT;
}
- json = json_tokener_parse_verbose(cres->body, &jerr);
+ D("Parsing the JSON response\n");
+ parsed_response = jv_parse(cres->body);
- if (jerr != json_tokener_success) {
- D("Failed to parse json string\n");
+ if (!jv_is_valid(parsed_response)) {
+ D("Invalid response\n");
goto BAIL_OUT;
}
- json_object_object_get_ex(json, "response", &json_response);
- json_object_object_get_ex(json_response, "result", &json_result);
+ /* Preparing the queries */
+ jq = jq_init();
+ if (jq == NULL) { D("jq error with malloc"); goto BAIL_OUT; }
- jobj = json_object_array_get_idx(json_result,0);
- json_object_object_get_ex(jobj, "password", &pwdh);
- json_object_object_get_ex(jobj, "public_key", &pubkey);
- json_object_object_get_ex(jobj, "expiration", &expiration);
+ pwd = get_from_json(jq, options->rest_resp_passwd, jv_copy(parsed_response));
+ pbk = get_from_json(jq, options->rest_resp_pubkey, jv_copy(parsed_response));
- success = add_to_db(username,
- json_object_get_string(pwdh),
- json_object_get_string(pubkey),
- json_object_get_string(expiration));
+ /* Adding to the database */
+ success = add_to_db(username, pwd, pbk);
BAIL_OUT:
- if(!success) D("user %s not found\n", username);
+ D("User %s%s found\n", username, (success)?"":" not");
if(cres) free(cres);
if(endpoint_creds) free(endpoint_creds);
- json_object_put(jobj);
- json_object_put(json_result);
- json_object_put(json_response);
- json_object_put(json);
+
+ jv_free(parsed_response);
+ jq_teardown(&jq);
+
curl_easy_cleanup(curl);
curl_global_cleanup();
return success;
diff --git a/src/auth/config.c b/src/auth/config.c
index ec7a21dc..0010f0e1 100644
--- a/src/auth/config.c
+++ b/src/auth/config.c
@@ -25,6 +25,8 @@ cleanconfig(void)
if(!options->rest_endpoint ) { free((char*)options->rest_endpoint); }
if(!options->rest_user ) { free((char*)options->rest_user); }
if(!options->rest_password ) { free((char*)options->rest_password); }
+ if(!options->rest_resp_passwd ) { free((char*)options->rest_resp_passwd); }
+ if(!options->rest_resp_pubkey ) { free((char*)options->rest_resp_pubkey); }
if(!options->ssl_cert ) { free((char*)options->ssl_cert); }
if(!options->skel ) { free((char*)options->skel); }
free(options);
@@ -64,6 +66,9 @@ readconfig(const char* configfile)
options->ssl_cert = CEGA_CERT;
options->with_homedir = false;
options->skel = "/ega/skel";
+
+ options->rest_resp_passwd = ".password";
+ options->rest_resp_pubkey = ".pubkey";
/* Parse line by line */
while (getline(&line, &len, fp) > 0) {
@@ -102,6 +107,8 @@ readconfig(const char* configfile)
if(!strcmp(key, "rest_endpoint" )) { options->rest_endpoint = strdup(val); }
if(!strcmp(key, "rest_user" )) { options->rest_user = strdup(val); }
if(!strcmp(key, "rest_password" )) { options->rest_password = strdup(val); }
+ if(!strcmp(key, "rest_resp_passwd" )) { options->rest_resp_passwd=strdup(val); }
+ if(!strcmp(key, "rest_resp_pubkey" )) { options->rest_resp_pubkey=strdup(val); }
if(!strcmp(key, "rest_buffer_size" )) { options->rest_buffer_size = atoi(val); }
if(!strcmp(key, "ssl_cert" )) { options->ssl_cert = strdup(val); }
if(!strcmp(key, "enable_rest")) {
diff --git a/src/auth/config.h b/src/auth/config.h
index b1201a7c..239f84af 100644
--- a/src/auth/config.h
+++ b/src/auth/config.h
@@ -32,6 +32,8 @@ struct options_s {
const char* rest_endpoint; /* https://ega/user/ | returns a triplet in JSON format */
const char* rest_user;
const char* rest_password; /* for authentication: user:password */
+ const char* rest_resp_passwd; /* Searching with jq for the password field */
+ const char* rest_resp_pubkey; /* Searching with jq for the public key field */
int rest_buffer_size; /* 1024 */
const char* ssl_cert; /* path the SSL certificate to contact Central EGA */
From df990d8ef89cbd2162f8e39254f8381485310d14 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 30 Oct 2017 14:54:24 +0100
Subject: [PATCH 025/528] Removing expiration settings from the code. Still
used in the database
---
src/auth/backend.c | 8 +++-----
src/auth/backend.h | 2 +-
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/auth/backend.c b/src/auth/backend.c
index 4d52a10d..f768f7e7 100644
--- a/src/auth/backend.c
+++ b/src/auth/backend.c
@@ -180,17 +180,15 @@ account_valid(const char* username)
bool
-add_to_db(const char* username, const char* pwdh, const char* pubkey, const char* expiration)
+add_to_db(const char* username, const char* pwdh, const char* pubkey)
{
- /* Expiration is ignored, for the moment */
- const char* params[4] = { username, pwdh, pubkey, NULL };
- int nbparams = 3;
+ const char* params[3] = { username, pwdh, pubkey };
PGresult *res;
bool success;
D("Prepared Statement: %s\n", options->nss_add_user);
D("with VALUES('%s','%s','%s')\n", username, pwdh, pubkey);
- res = PQexecParams(conn, options->nss_add_user, nbparams, NULL, params, NULL, NULL, 0);
+ res = PQexecParams(conn, options->nss_add_user, 3, NULL, params, NULL, NULL, 0);
success = (PQresultStatus(res) == PGRES_TUPLES_OK);
if(!success) D("%s\n", PQerrorMessage(conn));
diff --git a/src/auth/backend.h b/src/auth/backend.h
index 760d2c88..b6f7ac42 100644
--- a/src/auth/backend.h
+++ b/src/auth/backend.h
@@ -12,7 +12,7 @@ void backend_close(void);
enum nss_status backend_get_userentry(const char *name, struct passwd *result, char** buffer, size_t* buflen, int* errnop);
-bool add_to_db(const char* username, const char* pwdh, const char* pubkey, const char* expiration);
+bool add_to_db(const char* username, const char* pwdh, const char* pubkey);
int account_valid(const char* username);
int session_refresh_user(const char* username);
From 7fe7ff5bde80067fdfa2382880e2c4f7f79f3bc8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 30 Oct 2017 14:55:21 +0100
Subject: [PATCH 026/528] Adjusting the endpoint
---
docker/entrypoints/inbox.sh | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index b26c7ec7..fc55d0c6 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -23,9 +23,11 @@ debug = ok_why_not
db_connection = host=${EGA_DB_IP} port=5432 dbname=lega user=${POSTGRES_USER} password=${POSTGRES_PASSWORD} connect_timeout=1 sslmode=disable
enable_rest = yes
-rest_endpoint = https://egatest.crg.eu/lega/v1/user/%s
+rest_endpoint = https://egatest.crg.eu/lega/v1/lega/user/%s
rest_user = ${CEGA_ENDPOINT_USER}
rest_password = ${CEGA_ENDPOINT_PASSWORD}
+rest_resp_passwd = .response.result[0].password
+rest_resp_pubkey = .response.result[0].public_key
##################
# NSS Queries
@@ -50,7 +52,7 @@ query="SELECT pubkey from users where elixir_id = '\${eid}' LIMIT 1"
PGPASSWORD=${POSTGRES_PASSWORD} psql -tqA -U ${POSTGRES_USER} -h ega_db -d lega -c "\${query}"
EOF
-chmod 755 /usr/local/bin/ega_ssh_keys.sh
+chmod 750 /usr/local/bin/ega_ssh_keys.sh
echo "Starting the SFTP server"
exec /usr/sbin/sshd -D -e
From 4509294b01cd09c87154a51471912a0083107460 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 30 Oct 2017 14:57:34 +0100
Subject: [PATCH 027/528] Updating inbox docker image with jq and not json-c
---
docker/images/inbox/Dockerfile | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/docker/images/inbox/Dockerfile b/docker/images/inbox/Dockerfile
index 149f6339..058b32a5 100644
--- a/docker/images/inbox/Dockerfile
+++ b/docker/images/inbox/Dockerfile
@@ -1,12 +1,13 @@
FROM centos:latest
LABEL maintainer "Frédéric Haziza, NBIS"
-RUN yum -y update && \
+RUN yum install -y epel-release && \
+ yum -y update && \
yum -y install gcc git make rsyslog \
openssh-server \
nss-tools nc nmap tcpdump lsof strace \
bash-completion bash-completion-extras \
- postgresql-devel pam-devel libcurl-devel json-c-devel
+ postgresql-devel pam-devel libcurl-devel jq-devel
##################################
RUN mkdir -p /usr/local/lib/ega
From 66b87ec815ff63f70c6bf5bc0f3fc0f31655c997 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 30 Oct 2017 15:13:53 +0100
Subject: [PATCH 028/528] Updating Assembler variable in the Makefile
---
src/auth/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/auth/Makefile b/src/auth/Makefile
index 4ad86e3f..6136e2c9 100644
--- a/src/auth/Makefile
+++ b/src/auth/Makefile
@@ -42,7 +42,7 @@ $(PAM_LIBRARY): $(HEADERS) $(PAM_OBJECTS)
blowfish/x86.o: blowfish/x86.S $(HEADERS)
@echo "Compiling $<"
- @$(CC) -c -o $@ $<
+ @$(AS) -o $@ $<
%.o: %.c $(HEADERS)
@echo "Compiling $<"
From 5b29f36d6b3dcc9d53ea0e93affa82b09ab33dce Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Mon, 30 Oct 2017 15:14:51 +0100
Subject: [PATCH 029/528] Rename cucumber to tests, add uploading and ingestion
tests, add readme.
---
.gitignore | 1 -
.../lega/cucumber/steps/Authentication.java | 50 ------
.../src/test/resources/authentication.feature | 7 -
{cucumber => tests}/.gitignore | 0
tests/README.md | 113 ++++++++++++
{cucumber => tests}/pom.xml | 29 ++++
.../java/se/nbis/lega/cucumber/TestUtils.java | 107 ++++++++++++
.../java/se/nbis/lega/cucumber/Tests.java | 2 +-
.../nbis/lega/cucumber/steps/Definitions.java | 161 ++++++++++++++++++
.../cucumber/features/authentication.feature | 8 +
.../cucumber/features/ingestion.feature | 12 ++
.../cucumber/features/uploading.feature | 10 ++
.../test/resources/simplelogger.properties | 1 +
13 files changed, 442 insertions(+), 59 deletions(-)
delete mode 100644 cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
delete mode 100644 cucumber/src/test/resources/authentication.feature
rename {cucumber => tests}/.gitignore (100%)
create mode 100644 tests/README.md
rename {cucumber => tests}/pom.xml (65%)
create mode 100644 tests/src/test/java/se/nbis/lega/cucumber/TestUtils.java
rename {cucumber => tests}/src/test/java/se/nbis/lega/cucumber/Tests.java (81%)
create mode 100644 tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java
create mode 100644 tests/src/test/resources/cucumber/features/authentication.feature
create mode 100644 tests/src/test/resources/cucumber/features/ingestion.feature
create mode 100644 tests/src/test/resources/cucumber/features/uploading.feature
create mode 100644 tests/src/test/resources/simplelogger.properties
diff --git a/.gitignore b/.gitignore
index 16be5669..435ae831 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,6 @@ tmp/
private/
loggers/
!src/lega/conf/loggers
-tests/
storage
# =====================================
diff --git a/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
deleted file mode 100644
index c40af112..00000000
--- a/cucumber/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package se.nbis.lega.cucumber.steps;
-
-import cucumber.api.java.Before;
-import cucumber.api.java8.En;
-import net.schmizz.sshj.SSHClient;
-import net.schmizz.sshj.sftp.SFTPClient;
-import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
-import org.junit.Assert;
-
-import java.io.File;
-import java.io.IOException;
-
-public class Authentication implements En {
-
- private static final String USERNAME = "john";
-
- private File privateKey;
-
- private SFTPClient sftp;
-
- @Before
- public void setUp() throws IOException {
- privateKey = new File("../docker/bootstrap/private/cega/users/" + USERNAME + ".sec");
- }
-
- public Authentication() {
- Given("I have a private key", () -> Assert.assertNotNull(privateKey));
-
- When("I try to connect to the LocalEGA inbox via SFTP using private key", () -> {
- try {
- SSHClient ssh = new SSHClient();
- ssh.addHostKeyVerifier(new PromiscuousVerifier());
- ssh.connect("localhost", 2222);
- ssh.authPublickey(USERNAME, privateKey.getPath());
- sftp = ssh.newSFTPClient();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- });
-
- Then("the operation is successful", () -> {
- try {
- Assert.assertEquals("inbox", sftp.ls("/").iterator().next().getName());
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- });
- }
-
-}
\ No newline at end of file
diff --git a/cucumber/src/test/resources/authentication.feature b/cucumber/src/test/resources/authentication.feature
deleted file mode 100644
index 1c1c6d80..00000000
--- a/cucumber/src/test/resources/authentication.feature
+++ /dev/null
@@ -1,7 +0,0 @@
-Feature: Authentication
- As a user I want to be able to authenticate against LocalEGA inbox
-
- Scenario: Authenticate against LocalEGA inbox using private key
- Given I have a private key
- When I try to connect to the LocalEGA inbox via SFTP using private key
- Then the operation is successful
\ No newline at end of file
diff --git a/cucumber/.gitignore b/tests/.gitignore
similarity index 100%
rename from cucumber/.gitignore
rename to tests/.gitignore
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 00000000..58a5ce43
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,113 @@
+Test suite
+===================
+
+![enter image description here](https://www.javacodegeeks.com/wp-content/uploads/2015/04/cucumber-strip.png)
+
+Our tests are written with [Cucumber framework](https://cucumber.io/) and they help us to maintain stable behaviour of the system using human-readable scenarios.
+
+----------
+
+Syntax
+-------------
+
+Cucumber tests use [Gherkin](https://cucumber.io/docs/reference) syntax for describing scenarios of the application:
+
+> Gherkin is plain-text English (or one of 60+ other languages) with a little extra structure. Gherkin is designed to be easy to learn by non-programmers, yet structured enough to allow concise description of examples to illustrate business rules in most real-world domains.
+
+#### Example
+
+```gherkin
+Feature: Authentication
+ As a user I want to be able to authenticate against LocalEGA inbox
+
+ Scenario: Authenticate against LocalEGA inbox using private key
+ Given I am a user "john"
+ And I have a private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then I'm logged in successfully
+```
+
+----------
+
+
+Mapping
+-------------------
+
+Next step is about mapping Gherkin scenarios to executable code. Currently we use Java 8 to actually run tests-logic.
+
+#### Example
+
+```java
+ Given("^I am a user \"([^\"]*)\"$", (String user) -> this.user = user);
+
+ Given("^I have a private key$",
+ () -> privateKey = new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", user)));
+
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ try {
+ SSHClient ssh = new SSHClient();
+ ssh.addHostKeyVerifier(new PromiscuousVerifier());
+ ssh.connect("localhost", 2222);
+ ssh.authPublickey(user, privateKey.getPath());
+ sftp = ssh.newSFTPClient();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ Then("^I'm logged in successfully$", () -> {
+ try {
+ Assert.assertEquals("inbox", sftp.ls("/").iterator().next().getName());
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+```
+
+----------
+
+
+Execution
+-------------
+
+Test-suite is executed using Maven: `mvn clean test` from within the `tests` folder. Note that you obviously need to have LocalEGA up and running locally in order to execute the tests.
+
+#### Example
+
+```
+Feature: Uploading
+ As a user I want to be able to upload files to the LocalEGA inbox
+
+ Scenario: Upload files to the LocalEGA inbox # src/test/resources/cucumber/features/uploading.feature:4
+ Given I am a user "john" # Definitions.java:55
+ And I have a private key # Definitions.java:57
+ And I connect to the LocalEGA inbox via SFTP using private key # Definitions.java:60
+ And I have an encrypted file # Definitions.java:82
+ When I upload encrypted file to the LocalEGA inbox via SFTP # Definitions.java:106
+ Then the file is uploaded successfully # Definitions.java:115
+
+1 Scenarios (1 passed)
+6 Steps (6 passed)
+0m2.609s
+```
+
+----------
+
+
+Automation
+--------------------
+
+We've created the CI pipeline in order to automate test execution and maintain stability of the build. The job can be found here: https://travis-ci.org/NBISweden/LocalEGA
+
+Flow
+--------------------
+
+Behavior-driven development is a software development methodology which essentially states that for each feature of software, a software developer must:
+ - define a scenarios set for the feature first;
+ - make the scenarios fail;
+ - then implement the feature;
+ - finally verify that the implementation of the feature makes the scenarios succeed.
+
+So *ideally* one should always contribute new functionality along with a correspondent implemented test-case.
\ No newline at end of file
diff --git a/cucumber/pom.xml b/tests/pom.xml
similarity index 65%
rename from cucumber/pom.xml
rename to tests/pom.xml
index a7a9485c..13d58dbe 100644
--- a/cucumber/pom.xml
+++ b/tests/pom.xml
@@ -25,9 +25,26 @@
UTF-8
1.8
1.2.5
+ 1.58
+
+ org.projectlombok
+ lombok
+ 1.16.18
+ provided
+
+
+ org.slf4j
+ slf4j-api
+ LATEST
+
+
+ org.slf4j
+ slf4j-simple
+ LATEST
+
commons-io
commons-io
@@ -40,6 +57,18 @@
0.22.0
test
+
+ com.github.docker-java
+ docker-java
+ 3.0.13
+ test
+
+
+ org.assertj
+ assertj-core
+ 3.8.0
+ test
+
info.cukes
cucumber-java8
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/TestUtils.java b/tests/src/test/java/se/nbis/lega/cucumber/TestUtils.java
new file mode 100644
index 00000000..c7fe35c5
--- /dev/null
+++ b/tests/src/test/java/se/nbis/lega/cucumber/TestUtils.java
@@ -0,0 +1,107 @@
+package se.nbis.lega.cucumber;
+
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.model.Container;
+import com.github.dockerjava.core.DefaultDockerClientConfig;
+import com.github.dockerjava.core.DockerClientBuilder;
+import com.github.dockerjava.core.command.ExecStartResultCallback;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.ArrayUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Paths;
+
+/**
+ * Utility methods for the test-suite.
+ */
+public class TestUtils {
+
+ private DockerClient dockerClient;
+
+ /**
+ * Public constructor with Docker client initialization.
+ */
+ public TestUtils() {
+ this.dockerClient = DockerClientBuilder.getInstance(DefaultDockerClientConfig.createDefaultConfigBuilder().build()).build();
+ }
+
+ /**
+ * Executes shell command within specified container.
+ *
+ * @param container Container to execute command in.
+ * @param command Command to execute.
+ * @return Command output.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the command execution is interrupted.
+ */
+ public String executeWithinContainer(Container container, String... command) throws IOException, InterruptedException {
+ String execId = dockerClient.
+ execCreateCmd(container.getId()).
+ withCmd(command).
+ withAttachStdout(true).
+ withAttachStderr(true).
+ exec().
+ getId();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ExecStartResultCallback resultCallback = new ExecStartResultCallback(outputStream, System.err);
+ dockerClient.execStartCmd(execId).exec(resultCallback);
+ resultCallback.awaitCompletion();
+ return new String(outputStream.toByteArray());
+ }
+
+ /**
+ * Reads property from the trace file.
+ *
+ * @param property Property name.
+ * @return Property value.
+ * @throws IOException In case it's not possible to read trace file.
+ */
+ public String readTraceProperty(String property) throws IOException {
+ File trace = new File(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/.trace");
+ return FileUtils.readLines(trace, Charset.defaultCharset()).
+ stream().
+ filter(l -> l.startsWith(property)).
+ map(p -> p.split(" = ")[1]).
+ findAny().orElse(null);
+ }
+
+ /**
+ * Finds container by image name and container name.
+ *
+ * @param imageName Image name.
+ * @param containerName Container name.
+ * @return Docker container.
+ */
+ public Container findContainer(String imageName, String containerName) {
+ return dockerClient.listContainersCmd().exec().
+ stream().
+ filter(c -> c.getImage().equals(imageName)).
+ filter(c -> ArrayUtils.contains(c.getNames(), containerName)).
+ findAny().
+ orElse(null);
+ }
+
+ /**
+ * Calculates MD5 hash of a file.
+ *
+ * @param file File to calculate hash for.
+ * @return MD5 hash.
+ * @throws IOException In case it's not possible ot read the file.
+ */
+ public String calculateMD5(File file) throws IOException {
+ FileInputStream fileInputStream = new FileInputStream(file);
+ String md5 = DigestUtils.md5Hex(fileInputStream);
+ fileInputStream.close();
+ return md5;
+ }
+
+ public DockerClient getDockerClient() {
+ return dockerClient;
+ }
+
+}
diff --git a/cucumber/src/test/java/se/nbis/lega/cucumber/Tests.java b/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
similarity index 81%
rename from cucumber/src/test/java/se/nbis/lega/cucumber/Tests.java
rename to tests/src/test/java/se/nbis/lega/cucumber/Tests.java
index ce0f644c..9cd0c032 100644
--- a/cucumber/src/test/java/se/nbis/lega/cucumber/Tests.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
@@ -7,7 +7,7 @@
@RunWith(Cucumber.class)
@CucumberOptions(
format = {"pretty", "html:target/cucumber"},
- features = "classpath:authentication.feature"
+ features = "src/test/resources/cucumber/features"
)
public class Tests {
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java
new file mode 100644
index 00000000..0f71b0db
--- /dev/null
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java
@@ -0,0 +1,161 @@
+package se.nbis.lega.cucumber.steps;
+
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.model.AccessMode;
+import com.github.dockerjava.api.model.Bind;
+import com.github.dockerjava.api.model.Volume;
+import com.github.dockerjava.core.command.WaitContainerResultCallback;
+import cucumber.api.java.After;
+import cucumber.api.java.Before;
+import cucumber.api.java8.En;
+import lombok.extern.slf4j.Slf4j;
+import net.schmizz.sshj.SSHClient;
+import net.schmizz.sshj.sftp.RemoteResourceInfo;
+import net.schmizz.sshj.sftp.SFTPClient;
+import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
+import org.apache.commons.io.FileUtils;
+import org.assertj.core.api.Assertions;
+import org.junit.Assert;
+import se.nbis.lega.cucumber.TestUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Paths;
+
+@Slf4j
+public class Definitions implements En {
+
+ private TestUtils testUtils = new TestUtils();
+
+ private String user;
+ private File privateKey;
+ private String cegaMQUser;
+ private String cegaMQPassword;
+ private SFTPClient sftp;
+ private File dataFolder;
+ private File rawFile;
+ private File encryptedFile;
+
+ @Before
+ public void setUp() throws IOException {
+ dataFolder = new File("data");
+ dataFolder.mkdir();
+ rawFile = File.createTempFile("data", ".raw", dataFolder);
+ FileUtils.writeStringToFile(rawFile, "hello", Charset.defaultCharset());
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ FileUtils.deleteDirectory(dataFolder);
+ }
+
+ public Definitions() {
+ Given("^I am a user \"([^\"]*)\"$", (String user) -> this.user = user);
+
+ Given("^I have a private key$",
+ () -> privateKey = new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", user)));
+
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ try {
+ SSHClient ssh = new SSHClient();
+ ssh.addHostKeyVerifier(new PromiscuousVerifier());
+ ssh.connect("localhost", 2222);
+ ssh.authPublickey(user, privateKey.getPath());
+ sftp = ssh.newSFTPClient();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ Then("^I'm logged in successfully$", () -> {
+ try {
+ Assert.assertEquals("inbox", sftp.ls("/").iterator().next().getName());
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ Given("^I have an encrypted file$", () -> {
+ DockerClient dockerClient = testUtils.getDockerClient();
+ try {
+ Volume dataVolume = new Volume("/data");
+ Volume gpgVolume = new Volume("/root/.gnupg");
+ CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerCmd("nbis/ega:worker").
+ withVolumes(dataVolume, gpgVolume).
+ withBinds(new Bind(dataFolder.getAbsolutePath(), dataVolume),
+ new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
+ withCmd(testUtils.readTraceProperty("GPG exec"), "-r", testUtils.readTraceProperty("GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
+ exec();
+ dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
+ WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
+ dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback);
+ resultCallback.awaitCompletion();
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).exec();
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ encryptedFile = new File(rawFile.getAbsolutePath() + ".enc");
+ });
+
+ When("^I upload encrypted file to the LocalEGA inbox via SFTP$", () -> {
+ try {
+ sftp.put(encryptedFile.getAbsolutePath(), encryptedFile.getName());
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ Then("^the file is uploaded successfully$", () -> {
+ try {
+ Assert.assertTrue(sftp.ls("/inbox").stream().map(RemoteResourceInfo::getName).anyMatch(n -> encryptedFile.getName().equals(n)));
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ Given("^I have CEGA username and password$", () -> {
+ try {
+ cegaMQUser = testUtils.readTraceProperty("CEGA_MQ_USER");
+ cegaMQPassword = testUtils.readTraceProperty("CEGA_MQ_PASSWORD");
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ When("^I ingest file from the LocalEGA inbox$", () -> {
+ try {
+ testUtils.executeWithinContainer(testUtils.findContainer("nbis/ega:cega_mq", "/cega_mq"),
+ String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
+ cegaMQUser, cegaMQPassword, testUtils.readTraceProperty("CEGA_MQ_VHOST"), user, encryptedFile.getName(), testUtils.calculateMD5(rawFile), testUtils.calculateMD5(encryptedFile)).split(" "));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ Then("^the file is ingested successfully$", () -> {
+ try {
+ Thread.sleep(1000);
+ String query = String.format("select stable_id from files where filename = '%s'", encryptedFile.getName());
+ String output = testUtils.executeWithinContainer(testUtils.findContainer("nbis/ega:db", "/ega_db"),
+ "psql", "-U", testUtils.readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
+ String vaultFileName = output.split(System.getProperty("line.separator"))[2];
+ String cat = testUtils.executeWithinContainer(testUtils.findContainer("nbis/ega:common", "/ega_vault"), "cat", vaultFileName.trim());
+ Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
new file mode 100644
index 00000000..4828a3fb
--- /dev/null
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -0,0 +1,8 @@
+Feature: Authentication
+ As a user I want to be able to authenticate against LocalEGA inbox
+
+ Scenario: Authenticate against LocalEGA inbox using private key
+ Given I am a user "john"
+ And I have a private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then I'm logged in successfully
\ No newline at end of file
diff --git a/tests/src/test/resources/cucumber/features/ingestion.feature b/tests/src/test/resources/cucumber/features/ingestion.feature
new file mode 100644
index 00000000..d93b426e
--- /dev/null
+++ b/tests/src/test/resources/cucumber/features/ingestion.feature
@@ -0,0 +1,12 @@
+Feature: Ingestion
+ As a user I want to be able to ingest files from the LocalEGA inbox
+
+ Scenario: Ingest files from the LocalEGA inbox
+ Given I am a user "john"
+ And I have a private key
+ And I connect to the LocalEGA inbox via SFTP using private key
+ And I have an encrypted file
+ And I upload encrypted file to the LocalEGA inbox via SFTP
+ And I have CEGA username and password
+ When I ingest file from the LocalEGA inbox
+ Then the file is ingested successfully
\ No newline at end of file
diff --git a/tests/src/test/resources/cucumber/features/uploading.feature b/tests/src/test/resources/cucumber/features/uploading.feature
new file mode 100644
index 00000000..12abdbf5
--- /dev/null
+++ b/tests/src/test/resources/cucumber/features/uploading.feature
@@ -0,0 +1,10 @@
+Feature: Uploading
+ As a user I want to be able to upload files to the LocalEGA inbox
+
+ Scenario: Upload files to the LocalEGA inbox
+ Given I am a user "john"
+ And I have a private key
+ And I connect to the LocalEGA inbox via SFTP using private key
+ And I have an encrypted file
+ When I upload encrypted file to the LocalEGA inbox via SFTP
+ Then the file is uploaded successfully
\ No newline at end of file
diff --git a/tests/src/test/resources/simplelogger.properties b/tests/src/test/resources/simplelogger.properties
new file mode 100644
index 00000000..19774762
--- /dev/null
+++ b/tests/src/test/resources/simplelogger.properties
@@ -0,0 +1 @@
+org.slf4j.simpleLogger.defaultLogLevel=error
\ No newline at end of file
From 2b7f13f0f4f6124758fc5605b930fef4ba0ce7c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 30 Oct 2017 15:15:26 +0100
Subject: [PATCH 030/528] Default values in auth.conf.sample
---
src/auth/auth.conf.sample | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/auth/auth.conf.sample b/src/auth/auth.conf.sample
index 1cb0fd1f..dc8e9c77 100644
--- a/src/auth/auth.conf.sample
+++ b/src/auth/auth.conf.sample
@@ -6,11 +6,11 @@ debug = ok_why_not
db_connection = host=ega_db port=5432 dbname=lega user=postgres password=CHANGE-ME-PLEASE connect_timeout=1 sslmode=disable
enable_rest = yes
-rest_endpoint = http://central_ega/user/%s
+rest_endpoint = http://cega_users/user/%s
rest_user = lega
rest_password = change_me
-rest_resp_passwd = .response.result[0].password
-rest_resp_pubkey = .response.result[0].public_key
+rest_resp_passwd = .password
+rest_resp_pubkey = .public_key
##################
# NSS Queries
From 59cd75be88aeb4204547986f14c2b206f1244434 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 30 Oct 2017 15:16:37 +0100
Subject: [PATCH 031/528] Unused #define BCRYPT_HASHSIZE (64)
---
src/auth/backend.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/auth/backend.c b/src/auth/backend.c
index f768f7e7..2bfd02a9 100644
--- a/src/auth/backend.c
+++ b/src/auth/backend.c
@@ -21,8 +21,6 @@
#define COL_DIR 5
#define COL_SHELL 6
-#define BCRYPT_HASHSIZE (64)
-
static PGconn* conn;
/* connect to database */
From 6af2c49daa873fc3f5a7d675cca7db78a1e156d0 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Mon, 30 Oct 2017 15:25:50 +0100
Subject: [PATCH 032/528] Fix tests folder in .travis.yml file.
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index c4c116b7..8c4230ac 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,5 +12,5 @@ script:
- bootstrap/populate.sh
- sudo chown -R $USER .
- docker-compose up -d
- - cd ../cucumber
+ - cd ../test
- mvn test -B
From 8bda1faa239a32cc9ff1fbee84515b8bfad95072 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Mon, 30 Oct 2017 15:36:10 +0100
Subject: [PATCH 033/528] Fix tests folder in .travis.yml file.
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 8c4230ac..8cf48c2a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,5 +12,5 @@ script:
- bootstrap/populate.sh
- sudo chown -R $USER .
- docker-compose up -d
- - cd ../test
+ - cd ../tests
- mvn test -B
From 5e1b2f735604e6295ab6273f774701f42931beda Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 30 Oct 2017 15:46:33 +0100
Subject: [PATCH 034/528] Parametrizing the CEGA endpoint settings
---
docker/entrypoints/inbox.sh | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index fc55d0c6..b6a45d69 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -23,11 +23,11 @@ debug = ok_why_not
db_connection = host=${EGA_DB_IP} port=5432 dbname=lega user=${POSTGRES_USER} password=${POSTGRES_PASSWORD} connect_timeout=1 sslmode=disable
enable_rest = yes
-rest_endpoint = https://egatest.crg.eu/lega/v1/lega/user/%s
+rest_endpoint = ${CEGA_ENDPOINT}
rest_user = ${CEGA_ENDPOINT_USER}
rest_password = ${CEGA_ENDPOINT_PASSWORD}
-rest_resp_passwd = .response.result[0].password
-rest_resp_pubkey = .response.result[0].public_key
+rest_resp_passwd = ${CEGA_ENDPOINT_RESP_PASSWD}
+rest_resp_pubkey = ${CEGA_ENDPOINT_RESP_PUBKEY}
##################
# NSS Queries
From 344fa79986b1149f1737a2eb6193c26158e866b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 30 Oct 2017 16:54:23 +0100
Subject: [PATCH 035/528] Removing comments
---
docker/ega.yml | 11 -----------
docker/entrypoints/inbox.sh | 1 -
src/auth/cega.c | 8 ++++----
3 files changed, 4 insertions(+), 16 deletions(-)
diff --git a/docker/ega.yml b/docker/ega.yml
index d74dd35a..c628a4ac 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -44,7 +44,6 @@ services:
hostname: ega_inbox
depends_on:
- db
-# - cega_users
env_file:
- .env.d/db
- .env.d/cega
@@ -142,16 +141,6 @@ services:
# image: nbis/ega:monitors
# command: ["rsyslogd", "-n"]
- # # Faking Central EGA
- # cega_users:
- # build: images/cega_users
- # image: nbis/ega:cega_users
- # container_name: cega_users
- # ports:
- # - "9100:80"
- # volumes:
- # - ${CEGA_USERS}:/cega/users:rw
-
cega_mq:
build: images/cega_mq
hostname: cega_mq
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index b6a45d69..d319426b 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -40,7 +40,6 @@ nss_add_user = SELECT insert_user(\$1,\$2,\$3)
##################
pam_auth = SELECT password_hash FROM users WHERE elixir_id = \$1 LIMIT 1
pam_acct = SELECT elixir_id FROM users WHERE elixir_id = \$1 and current_timestamp < last_accessed + expiration
-#pam_prompt = wazzaaaa:
EOF
cat > /usr/local/bin/ega_ssh_keys.sh <ssl_cert); */
/* curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE , "PEM" ); */
-/* #ifdef DEBUG */
-/* curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); */
-/* curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); */
-/* #endif */
+#ifdef DEBUG
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+#endif
/* Perform the request, res will get the return code */
D("Connecting to %s\n", endpoint);
From 39588df0afd7ab840753a7cdf02b3a37634d2949 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 31 Oct 2017 11:08:29 +0100
Subject: [PATCH 036/528] Fixing the CEGA stubs
---
docker/bootstrap/generate.sh | 137 +++++++++++++++++++++++------------
docker/ega.yml | 13 +++-
2 files changed, 100 insertions(+), 50 deletions(-)
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index 91a5b3df..8ed28cac 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -44,6 +44,7 @@ function usage {
echo -e "\t--db_password \tDatabase username and password"
echo -e "\t--db_try \tDatabase connection attempts"
echo -e "\t \t[User default: ${DB_USER} | Connection attempts default: ${DB_TRY}]"
+ echo -e ""
echo -e "\t--cega_mq_user ,"
echo -e "\t--cega_mq_password ,"
echo -e "\t--cega_mq_vhost , \tUsername, password, vhost for the Central EGA message broker"
@@ -135,45 +136,6 @@ function generate_password {
[[ -z $DB_PASSWORD ]] && DB_PASSWORD=$(generate_password 16)
[[ -z $CEGA_MQ_PASSWORD ]] && CEGA_MQ_PASSWORD=$(generate_password 16)
-EGA_USER_PASSWORD_JOHN=$(generate_password 16)
-${OPENSSL} genrsa -out $ABS_PRIVATE/cega/users/john.sec -passout pass:${EGA_USER_PASSWORD_JOHN} 2048
-${OPENSSL} rsa -in $ABS_PRIVATE/cega/users/john.sec -passin pass:${EGA_USER_PASSWORD_JOHN} -pubout -out $ABS_PRIVATE/cega/users/john.pub
-chmod 400 $ABS_PRIVATE/cega/users/john.sec
-EGA_USER_PUBKEY_JOHN=$(ssh-keygen -i -mPKCS8 -f $ABS_PRIVATE/cega/users/john.pub)
-
-EGA_USER_PASSWORD_JANE=$(generate_password 16)
-${OPENSSL} genrsa -out $ABS_PRIVATE/cega/users/jane.sec -passout pass:${EGA_USER_PASSWORD_JANE} 2048
-${OPENSSL} rsa -in $ABS_PRIVATE/cega/users/jane.sec -passin pass:${EGA_USER_PASSWORD_JANE} -pubout -out $ABS_PRIVATE/cega/users/jane.pub
-chmod 400 $ABS_PRIVATE/cega/users/jane.sec
-EGA_USER_PUBKEY_JANE=$(ssh-keygen -i -mPKCS8 -f $ABS_PRIVATE/cega/users/jane.pub)
-
-EGA_USER_PASSWORD_TAYLOR=$(generate_password 16)
-
-cat > $ABS_PRIVATE/.trace < $ABS_PRIVATE/cega/users/john.yml < $ABS_PRIVATE/cega/users/jane.yml < $ABS_PRIVATE/cega/users/taylor.yml < $ABS_PRIVATE/keys.conf < $ABS_PRIVATE/cega/mq/defs.json < $ABS_PRIVATE/cega/mq/defs.json < $ABS_PRIVATE/.env.d/db < $ABS_PRIVATE/.env.d/gpg < $ABS_PRIVATE/.env.d/cega < $ABS_PRIVATE/.trace <
+CEGA_ENDPOINT_RESP_PASSWD= .password_hash
+CEGA_ENDPOINT_RESP_PUBKEY= .pubkey
+#
+EGA_USER_PASSWORD_JOHN = ${EGA_USER_PASSWORD_JOHN}
+EGA_USER_PUBKEY_JOHN = /$PRIVATE/cega/users/john.pub
+EGA_USER_PUBKEY_JANE = /$PRIVATE/cega/users/jane.pub
+EGA_USER_PASSWORD_TAYLOR = ${EGA_USER_PASSWORD_TAYLOR}
+#
+CEGA_MQ_USER = ${CEGA_MQ_USER}
+CEGA_MQ_PASSWORD = ${CEGA_MQ_PASSWORD}
+CEGA_MQ_VHOST = ${CEGA_MQ_VHOST}
+EOF
+[[ $VERBOSE == 'yes' ]] && cat $ABS_PRIVATE/.trace
diff --git a/docker/ega.yml b/docker/ega.yml
index c628a4ac..56618d7f 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -64,7 +64,6 @@ services:
depends_on:
- db
- mq
- - cega_mq
- inbox
hostname: ega_vault
container_name: ega_vault
@@ -83,7 +82,6 @@ services:
depends_on:
- db
- mq
- - cega_mq
- keys
- inbox
image: nbis/ega:worker
@@ -141,6 +139,8 @@ services:
# image: nbis/ega:monitors
# command: ["rsyslogd", "-n"]
+ # Faking Central EGA
+
cega_mq:
build: images/cega_mq
hostname: cega_mq
@@ -151,6 +151,15 @@ services:
volumes:
- ${CEGA_MQ_DEFS}:/etc/rabbitmq/defs.json:ro
+ cega_users:
+ build: images/cega_users
+ image: nbis/ega:cega_users
+ container_name: cega_users
+ ports:
+ - "9100:80"
+ volumes:
+ - ${CEGA_USERS}:/cega/users:rw
+
# Use the default driver for volume creation
volumes:
inbox:
From 20ad9854be58e4df492d75191223ac419c6ec081 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 31 Oct 2017 15:07:43 +0100
Subject: [PATCH 037/528] Fixing access permissions on the ega_keys script
---
docker/entrypoints/inbox.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index d319426b..f378b25e 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -52,6 +52,7 @@ query="SELECT pubkey from users where elixir_id = '\${eid}' LIMIT 1"
PGPASSWORD=${POSTGRES_PASSWORD} psql -tqA -U ${POSTGRES_USER} -h ega_db -d lega -c "\${query}"
EOF
chmod 750 /usr/local/bin/ega_ssh_keys.sh
+chgrp ega /usr/local/bin/ega_ssh_keys.sh
echo "Starting the SFTP server"
exec /usr/sbin/sshd -D -e
From ad220c41726c6e688f11603a25ba3c96047f45cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 31 Oct 2017 15:17:23 +0100
Subject: [PATCH 038/528] Fixing paths in .trace
---
docker/bootstrap/populate.sh | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/docker/bootstrap/populate.sh b/docker/bootstrap/populate.sh
index 869e1b1c..418106bd 100755
--- a/docker/bootstrap/populate.sh
+++ b/docker/bootstrap/populate.sh
@@ -98,4 +98,9 @@ EOF
cp -rf $ABS_PRIVATE/.env.d $HERE/../.env.d
+# Updating .trace with the right path
+if [[ -f $ABS_PRIVATE/.trace ]]; then
+ sed -i -e "s;;$HERE;" $ABS_PRIVATE/.trace
+fi
+
echomsg "docker-compose configuration files populated"
From 29c1a914fcd3c9330bcfed57bf4e6e5513f88c6c Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Tue, 31 Oct 2017 15:39:33 +0100
Subject: [PATCH 039/528] Add caching from nbis/ega Docker Hub repo.
---
.travis.yml | 25 +++++++++++++++++++------
docker/images/Makefile | 2 +-
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 8cf48c2a..33781b11 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,12 +5,25 @@ language: generic
services:
- docker
-script:
- - cd docker
- - make -C images
- - docker run --rm -i -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/generate.sh -f
- - bootstrap/populate.sh
- - sudo chown -R $USER .
+before_install:
+ - |
+ cd docker
+ docker pull -a nbis/ega
+ make -C images
+ docker run --rm -i -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/generate.sh -f
+ bootstrap/populate.sh
+ sudo chown -R $USER .
+
+install:
- docker-compose up -d
+
+script:
- cd ../tests
- mvn test -B
+
+after_success:
+ - |
+ if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
+ docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
+ docker push nbis/ega
+ fi
\ No newline at end of file
diff --git a/docker/images/Makefile b/docker/images/Makefile
index b9768fb8..0fdc87d8 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -6,7 +6,7 @@ all: $(EGA_IMAGES)
.PHONY: all $(EGA_IMAGES)
$(EGA_IMAGES):
- docker build -t nbis/ega:$@ $@
+ docker build --cache-from nbis/ega:$@ --tag nbis/ega:$@ $@
clean:
docker images | awk '/none/{print $$3}' | while read n; do docker rmi $$n; done
From c9ffe35dae8e34e75d4de1bfbde5065c58727368 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Wed, 1 Nov 2017 13:08:45 +0100
Subject: [PATCH 040/528] Introduce DI using picocontainer.
---
tests/pom.xml | 6 ++
.../java/se/nbis/lega/cucumber/Context.java | 20 +++++
.../cucumber/{TestUtils.java => Utils.java} | 4 +-
.../nbis/lega/cucumber/steps/Definitions.java | 77 +++++++++++--------
4 files changed, 71 insertions(+), 36 deletions(-)
create mode 100644 tests/src/test/java/se/nbis/lega/cucumber/Context.java
rename tests/src/test/java/se/nbis/lega/cucumber/{TestUtils.java => Utils.java} (98%)
diff --git a/tests/pom.xml b/tests/pom.xml
index 13d58dbe..07db0e3f 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -81,6 +81,12 @@
${cucumber.version}
test
+
+ info.cukes
+ cucumber-picocontainer
+ ${cucumber.version}
+ test
+
\ No newline at end of file
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Context.java b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
new file mode 100644
index 00000000..1e505640
--- /dev/null
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
@@ -0,0 +1,20 @@
+package se.nbis.lega.cucumber;
+
+import lombok.Data;
+import net.schmizz.sshj.sftp.SFTPClient;
+
+import java.io.File;
+
+@Data
+public class Context {
+
+ private String user;
+ private File privateKey;
+ private String cegaMQUser;
+ private String cegaMQPassword;
+ private SFTPClient sftp;
+ private File dataFolder;
+ private File rawFile;
+ private File encryptedFile;
+
+}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/TestUtils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
similarity index 98%
rename from tests/src/test/java/se/nbis/lega/cucumber/TestUtils.java
rename to tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index c7fe35c5..ad1d832f 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/TestUtils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -19,14 +19,14 @@
/**
* Utility methods for the test-suite.
*/
-public class TestUtils {
+public class Utils {
private DockerClient dockerClient;
/**
* Public constructor with Docker client initialization.
*/
- public TestUtils() {
+ public Utils() {
this.dockerClient = DockerClientBuilder.getInstance(DefaultDockerClientConfig.createDefaultConfigBuilder().build()).build();
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java
index 0f71b0db..b896dcae 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java
@@ -12,12 +12,12 @@
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.sftp.RemoteResourceInfo;
-import net.schmizz.sshj.sftp.SFTPClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
import org.apache.commons.io.FileUtils;
import org.assertj.core.api.Assertions;
import org.junit.Assert;
-import se.nbis.lega.cucumber.TestUtils;
+import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
import java.io.File;
import java.io.IOException;
@@ -27,43 +27,43 @@
@Slf4j
public class Definitions implements En {
- private TestUtils testUtils = new TestUtils();
+ private Context context;
+ private Utils utils;
- private String user;
- private File privateKey;
- private String cegaMQUser;
- private String cegaMQPassword;
- private SFTPClient sftp;
- private File dataFolder;
- private File rawFile;
- private File encryptedFile;
+ public Definitions(Context context) {
+ this();
+ this.context = context;
+ this.utils = new Utils();
+ }
@Before
public void setUp() throws IOException {
- dataFolder = new File("data");
+ File dataFolder = new File("data");
dataFolder.mkdir();
- rawFile = File.createTempFile("data", ".raw", dataFolder);
+ File rawFile = File.createTempFile("data", ".raw", dataFolder);
FileUtils.writeStringToFile(rawFile, "hello", Charset.defaultCharset());
+ context.setDataFolder(dataFolder);
+ context.setRawFile(rawFile);
}
@After
public void tearDown() throws IOException {
- FileUtils.deleteDirectory(dataFolder);
+ FileUtils.deleteDirectory(context.getDataFolder());
}
- public Definitions() {
- Given("^I am a user \"([^\"]*)\"$", (String user) -> this.user = user);
+ private Definitions() {
+ Given("^I am a user \"([^\"]*)\"$", (String user) -> context.setUser(user));
Given("^I have a private key$",
- () -> privateKey = new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", user)));
+ () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", context.getUser()))));
When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
- ssh.authPublickey(user, privateKey.getPath());
- sftp = ssh.newSFTPClient();
+ ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
+ context.setSftp(ssh.newSFTPClient());
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -72,7 +72,7 @@ public Definitions() {
Then("^I'm logged in successfully$", () -> {
try {
- Assert.assertEquals("inbox", sftp.ls("/").iterator().next().getName());
+ Assert.assertEquals("inbox", context.getSftp().ls("/").iterator().next().getName());
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -80,16 +80,17 @@ public Definitions() {
});
Given("^I have an encrypted file$", () -> {
- DockerClient dockerClient = testUtils.getDockerClient();
+ DockerClient dockerClient = utils.getDockerClient();
+ File rawFile = context.getRawFile();
try {
Volume dataVolume = new Volume("/data");
Volume gpgVolume = new Volume("/root/.gnupg");
CreateContainerResponse createContainerResponse = dockerClient.
createContainerCmd("nbis/ega:worker").
withVolumes(dataVolume, gpgVolume).
- withBinds(new Bind(dataFolder.getAbsolutePath(), dataVolume),
+ withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
- withCmd(testUtils.readTraceProperty("GPG exec"), "-r", testUtils.readTraceProperty("GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
+ withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
exec();
dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
@@ -100,12 +101,13 @@ public Definitions() {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
}
- encryptedFile = new File(rawFile.getAbsolutePath() + ".enc");
+ context.setEncryptedFile(new File(rawFile.getAbsolutePath() + ".enc"));
});
When("^I upload encrypted file to the LocalEGA inbox via SFTP$", () -> {
try {
- sftp.put(encryptedFile.getAbsolutePath(), encryptedFile.getName());
+ File encryptedFile = context.getEncryptedFile();
+ context.getSftp().put(encryptedFile.getAbsolutePath(), encryptedFile.getName());
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -114,7 +116,7 @@ public Definitions() {
Then("^the file is uploaded successfully$", () -> {
try {
- Assert.assertTrue(sftp.ls("/inbox").stream().map(RemoteResourceInfo::getName).anyMatch(n -> encryptedFile.getName().equals(n)));
+ Assert.assertTrue(context.getSftp().ls("/inbox").stream().map(RemoteResourceInfo::getName).anyMatch(n -> context.getEncryptedFile().getName().equals(n)));
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -123,8 +125,8 @@ public Definitions() {
Given("^I have CEGA username and password$", () -> {
try {
- cegaMQUser = testUtils.readTraceProperty("CEGA_MQ_USER");
- cegaMQPassword = testUtils.readTraceProperty("CEGA_MQ_PASSWORD");
+ context.setCegaMQUser(utils.readTraceProperty("CEGA_MQ_USER"));
+ context.setCegaMQPassword(utils.readTraceProperty("CEGA_MQ_PASSWORD"));
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -133,9 +135,16 @@ public Definitions() {
When("^I ingest file from the LocalEGA inbox$", () -> {
try {
- testUtils.executeWithinContainer(testUtils.findContainer("nbis/ega:cega_mq", "/cega_mq"),
+ File encryptedFile = context.getEncryptedFile();
+ utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "/cega_mq"),
String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
- cegaMQUser, cegaMQPassword, testUtils.readTraceProperty("CEGA_MQ_VHOST"), user, encryptedFile.getName(), testUtils.calculateMD5(rawFile), testUtils.calculateMD5(encryptedFile)).split(" "));
+ context.getCegaMQUser(),
+ context.getCegaMQPassword(),
+ utils.readTraceProperty("CEGA_MQ_VHOST"),
+ context.getUser(),
+ encryptedFile.getName(),
+ utils.calculateMD5(context.getRawFile()),
+ utils.calculateMD5(encryptedFile)).split(" "));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -145,11 +154,11 @@ public Definitions() {
Then("^the file is ingested successfully$", () -> {
try {
Thread.sleep(1000);
- String query = String.format("select stable_id from files where filename = '%s'", encryptedFile.getName());
- String output = testUtils.executeWithinContainer(testUtils.findContainer("nbis/ega:db", "/ega_db"),
- "psql", "-U", testUtils.readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
+ String query = String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName());
+ String output = utils.executeWithinContainer(utils.findContainer("nbis/ega:db", "/ega_db"),
+ "psql", "-U", utils.readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
String vaultFileName = output.split(System.getProperty("line.separator"))[2];
- String cat = testUtils.executeWithinContainer(testUtils.findContainer("nbis/ega:common", "/ega_vault"), "cat", vaultFileName.trim());
+ String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "/ega_vault"), "cat", vaultFileName.trim());
Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
From 26458fa3f294eb01ecccaa2cefdd3ab22a8b9eb5 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Wed, 1 Nov 2017 14:34:24 +0100
Subject: [PATCH 041/528] Split test steps into separate classes.
---
.../java/se/nbis/lega/cucumber/Context.java | 12 ++
.../java/se/nbis/lega/cucumber/Tests.java | 13 ++
.../lega/cucumber/steps/Authentication.java | 46 +++++
.../nbis/lega/cucumber/steps/Definitions.java | 170 ------------------
.../nbis/lega/cucumber/steps/Ingestion.java | 63 +++++++
.../nbis/lega/cucumber/steps/Uploading.java | 71 ++++++++
6 files changed, 205 insertions(+), 170 deletions(-)
create mode 100644 tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
delete mode 100644 tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java
create mode 100644 tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
create mode 100644 tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Context.java b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
index 1e505640..afcdb288 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Context.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
@@ -2,12 +2,17 @@
import lombok.Data;
import net.schmizz.sshj.sftp.SFTPClient;
+import org.apache.commons.io.FileUtils;
import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
@Data
public class Context {
+ private Utils utils = new Utils();
+
private String user;
private File privateKey;
private String cegaMQUser;
@@ -17,4 +22,11 @@ public class Context {
private File rawFile;
private File encryptedFile;
+ public Context() throws IOException {
+ dataFolder = new File("data");
+ dataFolder.mkdir();
+ rawFile = File.createTempFile("data", ".raw", dataFolder);
+ FileUtils.writeStringToFile(rawFile, "hello", Charset.defaultCharset());
+ }
+
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Tests.java b/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
index 9cd0c032..1c18e386 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
@@ -2,12 +2,25 @@
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
+import org.apache.commons.io.FileUtils;
+import org.junit.AfterClass;
import org.junit.runner.RunWith;
+import java.io.File;
+import java.io.IOException;
+
@RunWith(Cucumber.class)
@CucumberOptions(
format = {"pretty", "html:target/cucumber"},
features = "src/test/resources/cucumber/features"
)
public class Tests {
+
+ public static final String DATA_FOLDER_PATH = "data";
+
+ @AfterClass
+ public static void teardown() throws IOException {
+ FileUtils.deleteDirectory(new File(DATA_FOLDER_PATH));
+ }
+
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
new file mode 100644
index 00000000..3549c673
--- /dev/null
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -0,0 +1,46 @@
+package se.nbis.lega.cucumber.steps;
+
+import cucumber.api.java8.En;
+import lombok.extern.slf4j.Slf4j;
+import net.schmizz.sshj.SSHClient;
+import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
+import org.junit.Assert;
+import se.nbis.lega.cucumber.Context;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+
+@Slf4j
+public class Authentication implements En {
+
+ public Authentication(Context context) {
+ Given("^I am a user \"([^\"]*)\"$", context::setUser);
+
+ Given("^I have a private key$",
+ () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", context.getUser()))));
+
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ try {
+ SSHClient ssh = new SSHClient();
+ ssh.addHostKeyVerifier(new PromiscuousVerifier());
+ ssh.connect("localhost", 2222);
+ ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
+ context.setSftp(ssh.newSFTPClient());
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ Then("^I'm logged in successfully$", () -> {
+ try {
+ Assert.assertEquals("inbox", context.getSftp().ls("/").iterator().next().getName());
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java
deleted file mode 100644
index b896dcae..00000000
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Definitions.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package se.nbis.lega.cucumber.steps;
-
-import com.github.dockerjava.api.DockerClient;
-import com.github.dockerjava.api.command.CreateContainerResponse;
-import com.github.dockerjava.api.model.AccessMode;
-import com.github.dockerjava.api.model.Bind;
-import com.github.dockerjava.api.model.Volume;
-import com.github.dockerjava.core.command.WaitContainerResultCallback;
-import cucumber.api.java.After;
-import cucumber.api.java.Before;
-import cucumber.api.java8.En;
-import lombok.extern.slf4j.Slf4j;
-import net.schmizz.sshj.SSHClient;
-import net.schmizz.sshj.sftp.RemoteResourceInfo;
-import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
-import org.apache.commons.io.FileUtils;
-import org.assertj.core.api.Assertions;
-import org.junit.Assert;
-import se.nbis.lega.cucumber.Context;
-import se.nbis.lega.cucumber.Utils;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Paths;
-
-@Slf4j
-public class Definitions implements En {
-
- private Context context;
- private Utils utils;
-
- public Definitions(Context context) {
- this();
- this.context = context;
- this.utils = new Utils();
- }
-
- @Before
- public void setUp() throws IOException {
- File dataFolder = new File("data");
- dataFolder.mkdir();
- File rawFile = File.createTempFile("data", ".raw", dataFolder);
- FileUtils.writeStringToFile(rawFile, "hello", Charset.defaultCharset());
- context.setDataFolder(dataFolder);
- context.setRawFile(rawFile);
- }
-
- @After
- public void tearDown() throws IOException {
- FileUtils.deleteDirectory(context.getDataFolder());
- }
-
- private Definitions() {
- Given("^I am a user \"([^\"]*)\"$", (String user) -> context.setUser(user));
-
- Given("^I have a private key$",
- () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", context.getUser()))));
-
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
- try {
- SSHClient ssh = new SSHClient();
- ssh.addHostKeyVerifier(new PromiscuousVerifier());
- ssh.connect("localhost", 2222);
- ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
- context.setSftp(ssh.newSFTPClient());
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
- }
- });
-
- Then("^I'm logged in successfully$", () -> {
- try {
- Assert.assertEquals("inbox", context.getSftp().ls("/").iterator().next().getName());
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
- }
- });
-
- Given("^I have an encrypted file$", () -> {
- DockerClient dockerClient = utils.getDockerClient();
- File rawFile = context.getRawFile();
- try {
- Volume dataVolume = new Volume("/data");
- Volume gpgVolume = new Volume("/root/.gnupg");
- CreateContainerResponse createContainerResponse = dockerClient.
- createContainerCmd("nbis/ega:worker").
- withVolumes(dataVolume, gpgVolume).
- withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
- new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
- withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
- exec();
- dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
- WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
- dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback);
- resultCallback.awaitCompletion();
- dockerClient.removeContainerCmd(createContainerResponse.getId()).exec();
- } catch (IOException | InterruptedException e) {
- log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
- }
- context.setEncryptedFile(new File(rawFile.getAbsolutePath() + ".enc"));
- });
-
- When("^I upload encrypted file to the LocalEGA inbox via SFTP$", () -> {
- try {
- File encryptedFile = context.getEncryptedFile();
- context.getSftp().put(encryptedFile.getAbsolutePath(), encryptedFile.getName());
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
- }
- });
-
- Then("^the file is uploaded successfully$", () -> {
- try {
- Assert.assertTrue(context.getSftp().ls("/inbox").stream().map(RemoteResourceInfo::getName).anyMatch(n -> context.getEncryptedFile().getName().equals(n)));
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
- }
- });
-
- Given("^I have CEGA username and password$", () -> {
- try {
- context.setCegaMQUser(utils.readTraceProperty("CEGA_MQ_USER"));
- context.setCegaMQPassword(utils.readTraceProperty("CEGA_MQ_PASSWORD"));
- } catch (IOException e) {
- log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
- }
- });
-
- When("^I ingest file from the LocalEGA inbox$", () -> {
- try {
- File encryptedFile = context.getEncryptedFile();
- utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "/cega_mq"),
- String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
- context.getCegaMQUser(),
- context.getCegaMQPassword(),
- utils.readTraceProperty("CEGA_MQ_VHOST"),
- context.getUser(),
- encryptedFile.getName(),
- utils.calculateMD5(context.getRawFile()),
- utils.calculateMD5(encryptedFile)).split(" "));
- } catch (IOException | InterruptedException e) {
- log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
- }
- });
-
- Then("^the file is ingested successfully$", () -> {
- try {
- Thread.sleep(1000);
- String query = String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName());
- String output = utils.executeWithinContainer(utils.findContainer("nbis/ega:db", "/ega_db"),
- "psql", "-U", utils.readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
- String vaultFileName = output.split(System.getProperty("line.separator"))[2];
- String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "/ega_vault"), "cat", vaultFileName.trim());
- Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
- } catch (IOException | InterruptedException e) {
- log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
- }
- });
- }
-
-}
\ No newline at end of file
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
new file mode 100644
index 00000000..a2f6d831
--- /dev/null
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -0,0 +1,63 @@
+package se.nbis.lega.cucumber.steps;
+
+import cucumber.api.java8.En;
+import lombok.extern.slf4j.Slf4j;
+import org.assertj.core.api.Assertions;
+import org.junit.Assert;
+import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
+
+import java.io.File;
+import java.io.IOException;
+
+@Slf4j
+public class Ingestion implements En {
+
+ public Ingestion(Context context) {
+ Utils utils = context.getUtils();
+
+ Given("^I have CEGA username and password$", () -> {
+ try {
+ context.setCegaMQUser(utils.readTraceProperty("CEGA_MQ_USER"));
+ context.setCegaMQPassword(utils.readTraceProperty("CEGA_MQ_PASSWORD"));
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ When("^I ingest file from the LocalEGA inbox$", () -> {
+ try {
+ File encryptedFile = context.getEncryptedFile();
+ utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "/cega_mq"),
+ String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
+ context.getCegaMQUser(),
+ context.getCegaMQPassword(),
+ utils.readTraceProperty("CEGA_MQ_VHOST"),
+ context.getUser(),
+ encryptedFile.getName(),
+ utils.calculateMD5(context.getRawFile()),
+ utils.calculateMD5(encryptedFile)).split(" "));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ Then("^the file is ingested successfully$", () -> {
+ try {
+ Thread.sleep(1000);
+ String query = String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName());
+ String output = utils.executeWithinContainer(utils.findContainer("nbis/ega:db", "/ega_db"),
+ "psql", "-U", utils.readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
+ String vaultFileName = output.split(System.getProperty("line.separator"))[2];
+ String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "/ega_vault"), "cat", vaultFileName.trim());
+ Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
new file mode 100644
index 00000000..586cfcbf
--- /dev/null
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -0,0 +1,71 @@
+package se.nbis.lega.cucumber.steps;
+
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.model.AccessMode;
+import com.github.dockerjava.api.model.Bind;
+import com.github.dockerjava.api.model.Volume;
+import com.github.dockerjava.core.command.WaitContainerResultCallback;
+import cucumber.api.java8.En;
+import lombok.extern.slf4j.Slf4j;
+import net.schmizz.sshj.sftp.RemoteResourceInfo;
+import org.junit.Assert;
+import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+
+@Slf4j
+public class Uploading implements En {
+
+ public Uploading(Context context) {
+ Utils utils = context.getUtils();
+
+ Given("^I have an encrypted file$", () -> {
+ DockerClient dockerClient = utils.getDockerClient();
+ File rawFile = context.getRawFile();
+ try {
+ Volume dataVolume = new Volume("/data");
+ Volume gpgVolume = new Volume("/root/.gnupg");
+ CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerCmd("nbis/ega:worker").
+ withVolumes(dataVolume, gpgVolume).
+ withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
+ new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
+ withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
+ exec();
+ dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
+ WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
+ dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback);
+ resultCallback.awaitCompletion();
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).exec();
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ context.setEncryptedFile(new File(rawFile.getAbsolutePath() + ".enc"));
+ });
+
+ When("^I upload encrypted file to the LocalEGA inbox via SFTP$", () -> {
+ try {
+ File encryptedFile = context.getEncryptedFile();
+ context.getSftp().put(encryptedFile.getAbsolutePath(), encryptedFile.getName());
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+
+ Then("^the file is uploaded successfully$", () -> {
+ try {
+ Assert.assertTrue(context.getSftp().ls("/inbox").stream().map(RemoteResourceInfo::getName).anyMatch(n -> context.getEncryptedFile().getName().equals(n)));
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ });
+ }
+
+}
\ No newline at end of file
From 9254f7320389cec106dd712519a6d86b15b19a8e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 1 Nov 2017 16:59:03 +0100
Subject: [PATCH 042/528] Fixing the links on the contributing guidelines
---
CONTRIBUTING.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5578f0d2..7555a68f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -50,7 +50,7 @@ In short, the [AGILE method](https://www.zenhub.com/blog/how-to-use-github-agile
4) Work on it (on a fork, or on a separate branch) as you wish. That's
what `git` is good for. This GitHub repository follows
-the [coding guidelines from NBIS](/NBISweden/development-guidelines).
+the [coding guidelines from NBIS](https://github.com/NBISweden/development-guidelines).
Name your branch as you wish and prefix the name with:
* `feature/` if it is a code feature
@@ -80,7 +80,7 @@ the [coding guidelines from NBIS](/NBISweden/development-guidelines).
+ a `User story`
+ ... or several.
-Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
+ Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
6) Selecting a review goes as follows: Pick one _main_ reviewer. It
is usually one that you had discussions with, and is somehow
@@ -91,7 +91,7 @@ Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
merge the PR. Moreover, the main reviewer is the one merging the
PR, not you.
- Find more information on the [NBIS reviewing guidelines](/NBISweden/development-guidelines#how-we-do-code-reviews).
+ Find more information on the [NBIS reviewing guidelines](https://github.com/NBISweden/development-guidelines#how-we-do-code-reviews).
7) It is possible that your PR requires changes (because it creates
@@ -123,12 +123,12 @@ Do **_not_** ask us to merge it into `master`. We will use the `dev` branch.
## Did you find a bug?
* Ensure that the bug was not already reported by [searching under
- Issues](/NBISweden/LocalEGA/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Abug%20%5BBUG%5D%20in%3Atitle).
+ Issues](https://github.com/NBISweden/LocalEGA/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Abug%20%5BBUG%5D%20in%3Atitle).
* Do **_not_** file it as a plain GitHub issue (we use the issue
system for our internal tasks (see Zenhub)). If you're unable to
find an (open) issue addressing the problem, [open a new
- one](NBISweden/LocalEGA/issues/new?title=%5BBUG%5D). Be sure to
+ one](https://github.com/NBISweden/LocalEGA/issues/new?title=%5BBUG%5D). Be sure to
prefix the issue title with **[BUG]** and to include:
- a _clear_ description,
From 244fa35b351726b1f3e3bfba9226ab92449febf7 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Thu, 2 Nov 2017 10:39:41 +0100
Subject: [PATCH 043/528] Add Slack notifications from Travis CI.
---
.travis.yml | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 33781b11..e5d67ad0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -26,4 +26,8 @@ after_success:
if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
docker push nbis/ega
- fi
\ No newline at end of file
+ fi
+
+notifications:
+ slack:
+ secure: HYV1cipL+SFw4YFILZ+/BIn5TIZmQ5Opfwb3cUN+W6OPGm2yAiv4yvvsF4Kk6dIwoFxDNu/mdRLIX5kYCpFcfoFUZdRGk65kMpeXOcs6CzhgY6xILSEbD66rseayBHbvQ4Gd0xNoe+fdI28q0tphMkan4AVDyQwmDZNpk/1QqBpIugiBWQXY3UBXnXU5Yu5jIVPycPH70qQiU1R5BOn/Uw/pyDk9c/pH57sfGmzAMVyzp7UgN/sIbZ9MhTJZ1Dd6IRUO/DZJY8Z4ZkeUp7Mh8LHoQJyfwGqKH2rBGbpulXau43dtif1MvfQrI0xy2SUadlGSbUMmTKDay2mJquwS/uj1S2SrNi42VAZ6+in+f2qFLw34ZiyZKnVUiUKGAwo5ueSjN6aoEM1WT0YutflUhVGzm4dUhXLInpo0r7VNbkR2iOQ3qbdN4OqPaxZL34vHjbVMZkIuundbd1QTrGSJVGZVMmAwRUPrZhKqyvyDelZM1fV9e8ez+CNnq3XDWcVAuHiNp/NEiLZ42vc7/bXyOk3UBotEiBPseEDQddlZmd/mr56uD2qFFdfkyvNsywAKDPnw2qiXlVjUONOIfS9CdwPlbF2xQ5fNCoLEg40KWMopAICC6vGSHbPs3tkRq3LT2OgosMyrfBNeES12lLHi5KNoWtzEPs8WotHwHY4R75U=
From 0961957482eb059353cd3e51306450b60821ad63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 2 Nov 2017 13:57:28 +0100
Subject: [PATCH 044/528] No email notification from TravisCI. Slack
integration instead
---
.travis.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index e5d67ad0..fd500bf0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,7 @@ before_install:
docker pull -a nbis/ega
make -C images
docker run --rm -i -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/generate.sh -f
- bootstrap/populate.sh
+ bootstrap/populate.sh -f
sudo chown -R $USER .
install:
@@ -29,5 +29,6 @@ after_success:
fi
notifications:
+ email: false
slack:
secure: HYV1cipL+SFw4YFILZ+/BIn5TIZmQ5Opfwb3cUN+W6OPGm2yAiv4yvvsF4Kk6dIwoFxDNu/mdRLIX5kYCpFcfoFUZdRGk65kMpeXOcs6CzhgY6xILSEbD66rseayBHbvQ4Gd0xNoe+fdI28q0tphMkan4AVDyQwmDZNpk/1QqBpIugiBWQXY3UBXnXU5Yu5jIVPycPH70qQiU1R5BOn/Uw/pyDk9c/pH57sfGmzAMVyzp7UgN/sIbZ9MhTJZ1Dd6IRUO/DZJY8Z4ZkeUp7Mh8LHoQJyfwGqKH2rBGbpulXau43dtif1MvfQrI0xy2SUadlGSbUMmTKDay2mJquwS/uj1S2SrNi42VAZ6+in+f2qFLw34ZiyZKnVUiUKGAwo5ueSjN6aoEM1WT0YutflUhVGzm4dUhXLInpo0r7VNbkR2iOQ3qbdN4OqPaxZL34vHjbVMZkIuundbd1QTrGSJVGZVMmAwRUPrZhKqyvyDelZM1fV9e8ez+CNnq3XDWcVAuHiNp/NEiLZ42vc7/bXyOk3UBotEiBPseEDQddlZmd/mr56uD2qFFdfkyvNsywAKDPnw2qiXlVjUONOIfS9CdwPlbF2xQ5fNCoLEg40KWMopAICC6vGSHbPs3tkRq3LT2OgosMyrfBNeES12lLHi5KNoWtzEPs8WotHwHY4R75U=
From 54eabcd735223659f33314b3d69d6d56a0af76b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 2 Nov 2017 14:12:26 +0100
Subject: [PATCH 045/528] Copy mounted code somewhere else first
---
docker/entrypoints/frontend.sh | 3 ++-
docker/entrypoints/inbox.sh | 3 ++-
docker/entrypoints/ingest.sh | 3 ++-
docker/entrypoints/keys.sh | 3 ++-
docker/entrypoints/vault.sh | 3 ++-
5 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/docker/entrypoints/frontend.sh b/docker/entrypoints/frontend.sh
index 0c6b94e7..acde066f 100755
--- a/docker/entrypoints/frontend.sh
+++ b/docker/entrypoints/frontend.sh
@@ -2,7 +2,8 @@
set -e
-pip3.6 install /root/ega
+cp -r /root/ega /root/run
+pip3.6 install /root/run
echo "Starting the frontend"
exec ega-frontend
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index f378b25e..4dccdd44 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -6,7 +6,8 @@ chown root:ega /ega/inbox
chmod 750 /ega/inbox
chmod g+s /ega/inbox # setgid bit
-pushd /root/ega/auth
+cp -r /root/ega /root/run
+pushd /root/run/auth
make install clean
ldconfig -v
popd
diff --git a/docker/entrypoints/ingest.sh b/docker/entrypoints/ingest.sh
index ea1dda72..f203b82e 100755
--- a/docker/entrypoints/ingest.sh
+++ b/docker/entrypoints/ingest.sh
@@ -2,7 +2,8 @@
set -e
-pip3.6 install /root/ega
+cp -r /root/ega /root/run
+pip3.6 install /root/run
# echo "Waiting for Keyserver"
# until nc -4 --send-only ega_keys 9010 /dev/null; do sleep 1; done
diff --git a/docker/entrypoints/keys.sh b/docker/entrypoints/keys.sh
index b504a0ab..c8e887af 100755
--- a/docker/entrypoints/keys.sh
+++ b/docker/entrypoints/keys.sh
@@ -2,7 +2,8 @@
set -e
-pip3.6 install /root/ega
+cp -r /root/ega /root/run
+pip3.6 install /root/run
echo "Starting the key management server"
ega-keyserver --keys /etc/ega/keys.ini &
diff --git a/docker/entrypoints/vault.sh b/docker/entrypoints/vault.sh
index 527571a3..a3d1b013 100755
--- a/docker/entrypoints/vault.sh
+++ b/docker/entrypoints/vault.sh
@@ -2,7 +2,8 @@
set -e
-pip3.6 install /root/ega
+cp -r /root/ega /root/run
+pip3.6 install /root/run
echo "Waiting for Central Message Broker"
until nc -4 --send-only cega_mq 5672 /dev/null; do sleep 1; done
From 895bad1cf724be92638048abfc75407158513287 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 14:30:23 +0100
Subject: [PATCH 046/528] Refactor tests, add authentication tests.
---
docker/bootstrap/generate.sh | 2 +-
.../java/se/nbis/lega/cucumber/Context.java | 10 +-
.../java/se/nbis/lega/cucumber/Tests.java | 8 --
.../java/se/nbis/lega/cucumber/Utils.java | 44 ++++++++-
.../lega/cucumber/hooks/BeforeAfterHooks.java | 42 ++++++++
.../lega/cucumber/steps/Authentication.java | 99 ++++++++++++++++---
.../nbis/lega/cucumber/steps/Ingestion.java | 10 +-
.../nbis/lega/cucumber/steps/Uploading.java | 23 +++--
.../cucumber/features/authentication.feature | 34 ++++++-
.../cucumber/features/ingestion.feature | 5 +-
.../cucumber/features/uploading.feature | 5 +-
11 files changed, 230 insertions(+), 52 deletions(-)
create mode 100644 tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index 8ed28cac..a0285436 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -193,7 +193,7 @@ chmod 400 ${EGA_USER_SECKEY_JOHN}
${OPENSSL} genrsa -out ${EGA_USER_SECKEY_JANE} -passout pass:${EGA_USER_PASSWORD_JANE} 2048
${OPENSSL} rsa -in ${EGA_USER_SECKEY_JANE} -passin pass:${EGA_USER_PASSWORD_JANE} -pubout -out ${EGA_USER_PUBKEY_JANE}
-chmod 400 $ABS_PRIVATE/cega/users/jane.sec
+chmod 400 ${EGA_USER_SECKEY_JANE}
cat > $ABS_PRIVATE/cega/users/john.yml < c.getImage().equals(imageName)).
- filter(c -> ArrayUtils.contains(c.getNames(), containerName)).
+ filter(c -> ArrayUtils.contains(c.getNames(), "/" + containerName)).
findAny().
orElse(null);
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
new file mode 100644
index 00000000..30c3fb9d
--- /dev/null
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -0,0 +1,42 @@
+package se.nbis.lega.cucumber.hooks;
+
+import cucumber.api.java.After;
+import cucumber.api.java.Before;
+import cucumber.api.java8.En;
+import org.apache.commons.io.FileUtils;
+import se.nbis.lega.cucumber.Context;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+public class BeforeAfterHooks implements En {
+
+ private Context context;
+
+ public BeforeAfterHooks(Context context) {
+ this.context = context;
+ }
+
+ @Before
+ public void setUp() throws IOException {
+ File dataFolder = new File("data");
+ dataFolder.mkdir();
+ File rawFile = File.createTempFile("data", ".raw", dataFolder);
+ FileUtils.writeStringToFile(rawFile, "hello", Charset.defaultCharset());
+ context.setDataFolder(dataFolder);
+ context.setRawFile(rawFile);
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ FileUtils.deleteDirectory(context.getDataFolder());
+ String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
+ File cegaUsersFolder = new File(cegaUsersFolderPath);
+ Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
+ }
+
+}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 3549c673..e9e01aa0 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -1,46 +1,121 @@
package se.nbis.lega.cucumber.steps;
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.model.Bind;
+import com.github.dockerjava.api.model.Container;
+import com.github.dockerjava.api.model.Volume;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
+import net.schmizz.sshj.userauth.UserAuthException;
+import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.UUID;
@Slf4j
public class Authentication implements En {
public Authentication(Context context) {
- Given("^I am a user \"([^\"]*)\"$", context::setUser);
+ Utils utils = context.getUtils();
- Given("^I have a private key$",
+ Given("^I am a user$", () -> context.setUser(UUID.randomUUID().toString()));
+
+ Given("^I have an account at Central EGA$", () -> {
+ DockerClient dockerClient = utils.getDockerClient();
+ String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
+ String name = UUID.randomUUID().toString();
+ String dataFolderName = context.getDataFolder().getName();
+ CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerCmd("nbis/ega:worker").
+ withName(name).
+ withCmd("sleep", "1000").
+ withBinds(new Bind(cegaUsersFolderPath, new Volume("/" + dataFolderName))).
+ exec();
+ dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
+ try {
+ Container tempWorker = utils.findContainer("nbis/ega:worker", name);
+ double password = Math.random();
+ String user = context.getUser();
+ utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
+ String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
+ File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
+ FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ } finally {
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
+ }
+ });
+
+ Given("^I have correct private key$",
() -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", context.getUser()))));
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ Given("^I have incorrect private key$",
+ () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
+
+ When("^my account expires$", () -> {
+ authenticate(context);
+ try {
+ Thread.sleep(1000);
+ utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
+
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> authenticate(context));
+
+ Then("^I am in the local database$", () -> {
try {
- SSHClient ssh = new SSHClient();
- ssh.addHostKeyVerifier(new PromiscuousVerifier());
- ssh.connect("localhost", 2222);
- ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
- context.setSftp(ssh.newSFTPClient());
- } catch (IOException e) {
+ String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
+ String count = output.split(System.getProperty("line.separator"))[2];
+ Assert.assertEquals(1, Integer.parseInt(count.trim()));
+ } catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
}
});
- Then("^I'm logged in successfully$", () -> {
+ Then("^I am not in the local database$", () -> {
try {
- Assert.assertEquals("inbox", context.getSftp().ls("/").iterator().next().getName());
- } catch (IOException e) {
+ String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
+ String count = output.split(System.getProperty("line.separator"))[2];
+ Assert.assertEquals(0, Integer.parseInt(count.trim()));
+ } catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
}
});
+
+ Then("^I'm logged in successfully$", () -> Assert.assertFalse(context.isAuthenticationFailed()));
+
+ Then("^authentication fails$", () -> Assert.assertTrue(context.isAuthenticationFailed()));
+
+ }
+
+ private void authenticate(Context context) {
+ try {
+ SSHClient ssh = new SSHClient();
+ ssh.addHostKeyVerifier(new PromiscuousVerifier());
+ ssh.connect("localhost", 2222);
+ ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
+ context.setSftp(ssh.newSFTPClient());
+ } catch (UserAuthException e) {
+ log.error(e.getMessage(), e);
+ context.setAuthenticationFailed(true);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
}
}
\ No newline at end of file
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
index a2f6d831..3560a8d7 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -29,7 +29,7 @@ public Ingestion(Context context) {
When("^I ingest file from the LocalEGA inbox$", () -> {
try {
File encryptedFile = context.getEncryptedFile();
- utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "/cega_mq"),
+ utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "cega_mq"),
String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
context.getCegaMQUser(),
context.getCegaMQPassword(),
@@ -38,6 +38,7 @@ public Ingestion(Context context) {
encryptedFile.getName(),
utils.calculateMD5(context.getRawFile()),
utils.calculateMD5(encryptedFile)).split(" "));
+ Thread.sleep(1000);
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -46,12 +47,9 @@ public Ingestion(Context context) {
Then("^the file is ingested successfully$", () -> {
try {
- Thread.sleep(1000);
- String query = String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName());
- String output = utils.executeWithinContainer(utils.findContainer("nbis/ega:db", "/ega_db"),
- "psql", "-U", utils.readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
+ String output = utils.executeDBQuery(String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName()));
String vaultFileName = output.split(System.getProperty("line.separator"))[2];
- String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "/ega_vault"), "cat", vaultFileName.trim());
+ String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "ega_vault"), "cat", vaultFileName.trim());
Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index 586cfcbf..dcae27d6 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -26,24 +26,32 @@ public Uploading(Context context) {
Given("^I have an encrypted file$", () -> {
DockerClient dockerClient = utils.getDockerClient();
File rawFile = context.getRawFile();
+ String dataFolderName = context.getDataFolder().getName();
+ Volume dataVolume = new Volume("/" + dataFolderName);
+ Volume gpgVolume = new Volume("/root/.gnupg");
+ CreateContainerResponse createContainerResponse = null;
try {
- Volume dataVolume = new Volume("/data");
- Volume gpgVolume = new Volume("/root/.gnupg");
- CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerResponse = dockerClient.
createContainerCmd("nbis/ega:worker").
withVolumes(dataVolume, gpgVolume).
- withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
+ withBinds(new Bind(Paths.get(dataFolderName).toAbsolutePath().toString(), dataVolume),
new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
- withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
+ withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", String.format("/%s/%s.enc", dataFolderName, rawFile.getName()), String.format("/%s/%s", dataFolderName, rawFile.getName())).
exec();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ try {
dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback);
resultCallback.awaitCompletion();
- dockerClient.removeContainerCmd(createContainerResponse.getId()).exec();
- } catch (IOException | InterruptedException e) {
+ } catch (InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
+ } finally {
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
}
context.setEncryptedFile(new File(rawFile.getAbsolutePath() + ".enc"));
});
@@ -54,7 +62,6 @@ public Uploading(Context context) {
context.getSftp().put(encryptedFile.getAbsolutePath(), encryptedFile.getName());
} catch (IOException e) {
log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
}
});
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index 4828a3fb..166d0211 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -1,8 +1,36 @@
Feature: Authentication
As a user I want to be able to authenticate against LocalEGA inbox
- Scenario: Authenticate against LocalEGA inbox using private key
- Given I am a user "john"
- And I have a private key
+ Scenario: User population in LocalEGA DB from Central EGA
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then I am in the local database
+
+ Scenario: User doesn't exist in Central EGA, but tries to authenticate against LocalEGA inbox
+ Given I am a user
+ And I have correct private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
+ Scenario: User exists in Central EGA, but uses incorrect private key for authentication
+ Given I am a user
+ And I have an account at Central EGA
+ And I have incorrect private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
+ Scenario: User exists in Central EGA, but his account has expired
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
+ When my account expires
+ Then I am not in the local database
+
+ Scenario: User exists in Central EGA and uses correct private key for authentication
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then I'm logged in successfully
\ No newline at end of file
diff --git a/tests/src/test/resources/cucumber/features/ingestion.feature b/tests/src/test/resources/cucumber/features/ingestion.feature
index d93b426e..52804f16 100644
--- a/tests/src/test/resources/cucumber/features/ingestion.feature
+++ b/tests/src/test/resources/cucumber/features/ingestion.feature
@@ -2,8 +2,9 @@ Feature: Ingestion
As a user I want to be able to ingest files from the LocalEGA inbox
Scenario: Ingest files from the LocalEGA inbox
- Given I am a user "john"
- And I have a private key
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
And I upload encrypted file to the LocalEGA inbox via SFTP
diff --git a/tests/src/test/resources/cucumber/features/uploading.feature b/tests/src/test/resources/cucumber/features/uploading.feature
index 12abdbf5..9adf5c3c 100644
--- a/tests/src/test/resources/cucumber/features/uploading.feature
+++ b/tests/src/test/resources/cucumber/features/uploading.feature
@@ -2,8 +2,9 @@ Feature: Uploading
As a user I want to be able to upload files to the LocalEGA inbox
Scenario: Upload files to the LocalEGA inbox
- Given I am a user "john"
- And I have a private key
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
When I upload encrypted file to the LocalEGA inbox via SFTP
From 1714358657cfaae9b72dba04d339c2ec22ad2e66 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 16:52:48 +0100
Subject: [PATCH 047/528] Fix SFTP library bug (work-around). Use temp users in
testing.
---
.../lega/cucumber/hooks/BeforeAfterHooks.java | 3 ++-
.../nbis/lega/cucumber/steps/Authentication.java | 16 ++++++++++++----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index 30c3fb9d..bbf24f9f 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -32,11 +32,12 @@ public void setUp() throws IOException {
}
@After
- public void tearDown() throws IOException {
+ public void tearDown() throws IOException, InterruptedException {
FileUtils.deleteDirectory(context.getDataFolder());
String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
File cegaUsersFolder = new File(cegaUsersFolderPath);
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
+ context.getUtils().executeDBQuery(String.format("delete from users where elixir_id = '%s'", context.getUser()));
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index e9e01aa0..43d3c80c 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -47,6 +47,7 @@ public Authentication(Context context) {
String user = context.getUser();
utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("chmod 400 /%s/%s.sec", dataFolderName, user).split(" "));
String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
@@ -73,7 +74,9 @@ public Authentication(Context context) {
}
});
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> authenticate(context));
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ authenticate(context);
+ });
Then("^I am in the local database$", () -> {
try {
@@ -104,17 +107,22 @@ public Authentication(Context context) {
}
private void authenticate(Context context) {
+ // need to retry twice due to bug in SSHJ library
+ retryAuthenticationAttempt(context);
+ retryAuthenticationAttempt(context);
+ }
+
+ private void retryAuthenticationAttempt(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
context.setSftp(ssh.newSFTPClient());
- } catch (UserAuthException e) {
+ context.setAuthenticationFailed(false);
+ } catch (Exception e) {
log.error(e.getMessage(), e);
context.setAuthenticationFailed(true);
- } catch (IOException e) {
- log.error(e.getMessage(), e);
}
}
From e9c42ca35f73ff36fd2c92b3dc404a4c03c04340 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 17:17:35 +0100
Subject: [PATCH 048/528] Reuse single test user across all scenarios.
---
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 43d3c80c..1dfba558 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -9,7 +9,6 @@
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
-import net.schmizz.sshj.userauth.UserAuthException;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import se.nbis.lega.cucumber.Context;
@@ -27,7 +26,7 @@ public class Authentication implements En {
public Authentication(Context context) {
Utils utils = context.getUtils();
- Given("^I am a user$", () -> context.setUser(UUID.randomUUID().toString()));
+ Given("^I am a user$", () -> context.setUser("test"));
Given("^I have an account at Central EGA$", () -> {
DockerClient dockerClient = utils.getDockerClient();
@@ -107,12 +106,6 @@ public Authentication(Context context) {
}
private void authenticate(Context context) {
- // need to retry twice due to bug in SSHJ library
- retryAuthenticationAttempt(context);
- retryAuthenticationAttempt(context);
- }
-
- private void retryAuthenticationAttempt(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
From e39812d24dba9e84fce7e18ae637bec8bc138223 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 21:26:01 +0100
Subject: [PATCH 049/528] Change keys permissions in code, run tests as root.
---
.travis.yml | 2 +-
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 8 ++++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index fd500bf0..3b86dc5f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,7 +19,7 @@ install:
script:
- cd ../tests
- - mvn test -B
+ - sudo mvn test -B
after_success:
- |
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 1dfba558..76de69d7 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -16,8 +16,11 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
+import java.util.Collections;
import java.util.UUID;
@Slf4j
@@ -46,7 +49,6 @@ public Authentication(Context context) {
String user = context.getUser();
utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
- utils.executeWithinContainer(tempWorker, String.format("chmod 400 /%s/%s.sec", dataFolderName, user).split(" "));
String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
@@ -110,7 +112,9 @@ private void authenticate(Context context) {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
- ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
+ File privateKey = context.getPrivateKey();
+ Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
+ ssh.authPublickey(context.getUser(), privateKey.getPath());
context.setSftp(ssh.newSFTPClient());
context.setAuthenticationFailed(false);
} catch (Exception e) {
From d1c8dfad7de75aa2785dfe24287f427e6686d631 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sun, 5 Nov 2017 13:20:12 +0100
Subject: [PATCH 050/528] Cleanup inbox after tests execution.
---
.../java/se/nbis/lega/cucumber/Context.java | 2 ++
.../java/se/nbis/lega/cucumber/Utils.java | 17 ++++++++++--
.../lega/cucumber/hooks/BeforeAfterHooks.java | 9 ++++---
.../lega/cucumber/steps/Authentication.java | 26 ++++++++++++-------
4 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Context.java b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
index d7819dfd..11fe73a0 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Context.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
@@ -1,6 +1,7 @@
package se.nbis.lega.cucumber;
import lombok.Data;
+import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.sftp.SFTPClient;
import java.io.File;
@@ -14,6 +15,7 @@ public class Context {
private File privateKey;
private String cegaMQUser;
private String cegaMQPassword;
+ private SSHClient ssh;
private SFTPClient sftp;
private File dataFolder;
private File rawFile;
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index 2c248b01..cdcc3600 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -71,11 +71,24 @@ public String executeDBQuery(String query) throws IOException, InterruptedExcept
return executeWithinContainer(findContainer("nbis/ega:db", "ega_db"), "psql", "-U", readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
}
+ /**
+ * Checks if user exists in the local database.
+ *
+ * @param user Username.
+ * @return true
if user exists, false
otherwise.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public boolean isUserExistInDB(String user) throws IOException, InterruptedException {
+ String output = executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", user));
+ return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
+ }
+
/**
* Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
*
- * @param from Folder to mount from.
- * @param to Folder to mount to.
+ * @param from Folder to mount from.
+ * @param to Folder to mount to.
* @param command Command to execute.
* @throws InterruptedException In case the command execution is interrupted.
*/
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index bbf24f9f..b685ff08 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -5,9 +5,9 @@
import cucumber.api.java8.En;
import org.apache.commons.io.FileUtils;
import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
import java.io.File;
-import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Paths;
@@ -36,8 +36,11 @@ public void tearDown() throws IOException, InterruptedException {
FileUtils.deleteDirectory(context.getDataFolder());
String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
File cegaUsersFolder = new File(cegaUsersFolderPath);
- Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
- context.getUtils().executeDBQuery(String.format("delete from users where elixir_id = '%s'", context.getUser()));
+ Utils utils = context.getUtils();
+ String user = context.getUser();
+ Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
+ utils.executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ utils.executeWithinContainer(utils.findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 76de69d7..7fb7d6f1 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -66,7 +66,8 @@ public Authentication(Context context) {
() -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
When("^my account expires$", () -> {
- authenticate(context);
+ connect(context);
+ disconnect(context);
try {
Thread.sleep(1000);
utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
@@ -76,14 +77,12 @@ public Authentication(Context context) {
});
When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
- authenticate(context);
+ connect(context);
});
Then("^I am in the local database$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
- String count = output.split(System.getProperty("line.separator"))[2];
- Assert.assertEquals(1, Integer.parseInt(count.trim()));
+ Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -92,9 +91,7 @@ public Authentication(Context context) {
Then("^I am not in the local database$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
- String count = output.split(System.getProperty("line.separator"))[2];
- Assert.assertEquals(0, Integer.parseInt(count.trim()));
+ Assert.assertFalse(utils.isUserExistInDB(context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -107,7 +104,7 @@ public Authentication(Context context) {
}
- private void authenticate(Context context) {
+ private void connect(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
@@ -115,6 +112,8 @@ private void authenticate(Context context) {
File privateKey = context.getPrivateKey();
Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
ssh.authPublickey(context.getUser(), privateKey.getPath());
+
+ context.setSsh(ssh);
context.setSftp(ssh.newSFTPClient());
context.setAuthenticationFailed(false);
} catch (Exception e) {
@@ -123,4 +122,13 @@ private void authenticate(Context context) {
}
}
+ private void disconnect(Context context) {
+ try {
+ context.getSftp().close();
+ context.getSsh().disconnect();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+
}
\ No newline at end of file
From bd512829f1060e6e5b6dfb1dd24fb7a9b808458d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 6 Nov 2017 18:12:49 +0100
Subject: [PATCH 051/528] Multiple LEGA instances and fixing the database user
---
docker/bootstrap/generate.sh | 97 ++++++++++++++++++++---------
docker/ega.yml | 31 +++++++--
docker/entrypoints/inbox.sh | 3 +
docker/images/cega_users/Dockerfile | 1 -
docker/images/cega_users/server.py | 48 +++++++++++---
docker/images/cega_users/users.html | 14 +++--
docker/images/db/db.sql | 4 +-
docker/images/inbox/banner | 2 +-
src/auth/backend.c | 2 +-
src/auth/cega.c | 9 +--
10 files changed, 153 insertions(+), 58 deletions(-)
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index 8ed28cac..e95434cf 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -9,7 +9,7 @@ VERBOSE=yes
FORCE=no
SSL_SUBJ="/C=SE/ST=Sweden/L=Uppsala/O=NBIS/OU=SysDevs/CN=LocalEGA/emailAddress=ega@nbis.se"
PRIVATE=private
-DB_USER=postgres
+DB_USER=lega
DB_TRY=30
CEGA_MQ_USER=cega_sweden
CEGA_MQ_VHOST=se
@@ -83,12 +83,17 @@ while [[ $# -gt 0 ]]; do
shift
done
-exec 2>${HERE}/.err
[[ $VERBOSE == 'no' ]] && exec 1>${HERE}/.log && FORCE='yes'
+exec 2>${HERE}/.err
[[ -x $(readlink ${GPG}) ]] && echo "${GPG} is not executable" && exit 2
[[ -x $(readlink ${OPENSSL}) ]] && echo "${OPENSSL} is not executable" && exit 3
+if [ -z "${DB_USER}" -o "${DB_USER}" == "postgres" ]; then
+ echo "Choose a database user (but not 'postgres')"
+ exit 4
+fi
+
#########################################################################
# Creating the necessary folders
# Ask recreate them if already existing
@@ -136,6 +141,8 @@ function generate_password {
[[ -z $DB_PASSWORD ]] && DB_PASSWORD=$(generate_password 16)
[[ -z $CEGA_MQ_PASSWORD ]] && CEGA_MQ_PASSWORD=$(generate_password 16)
+LEGA_SWE1_PASSWORD=$(generate_password 16)
+LEGA_FIN1_PASSWORD=$(generate_password 16)
#########################################################################
# And....cue music
@@ -294,21 +301,51 @@ EOF
echo "Generating the docker-compose configuration files"
cat > $ABS_PRIVATE/.env.d/db < $ABS_PRIVATE/.env.d/gpg < $ABS_PRIVATE/.env.d/cega < $ABS_PRIVATE/.env.d/cega_instances < $ABS_PRIVATE/.env.d/cega.swe1 < $ABS_PRIVATE/.env.d/cega.fin1 < /dev/null
+ln -s ../john.yml .
+ln -s ../jane.yml .
+ln -s ../taylor.yml .
+popd > /dev/null
+# John has also access to FIN1
+pushd $ABS_PRIVATE/cega/users/fin1 > /dev/null
+ln -s ../john.yml .
+popd > /dev/null
+
#########################################################################
echo -e "\tGeneration completed" $'\xF0\x9F\x91\x8D'
@@ -317,32 +354,32 @@ cat > $ABS_PRIVATE/.trace <
-CEGA_ENDPOINT_RESP_PASSWD= .password_hash
-CEGA_ENDPOINT_RESP_PUBKEY= .pubkey
+EGA_USER_PASSWORD_JOHN = ${EGA_USER_PASSWORD_JOHN}
+EGA_USER_PUBKEY_JOHN = /$PRIVATE/cega/users/john.pub
+EGA_USER_PUBKEY_JANE = /$PRIVATE/cega/users/jane.pub
+EGA_USER_PASSWORD_TAYLOR = ${EGA_USER_PASSWORD_TAYLOR}
#
-EGA_USER_PASSWORD_JOHN = ${EGA_USER_PASSWORD_JOHN}
-EGA_USER_PUBKEY_JOHN = /$PRIVATE/cega/users/john.pub
-EGA_USER_PUBKEY_JANE = /$PRIVATE/cega/users/jane.pub
-EGA_USER_PASSWORD_TAYLOR = ${EGA_USER_PASSWORD_TAYLOR}
+CEGA_MQ_USER = ${CEGA_MQ_USER}
+CEGA_MQ_PASSWORD = ${CEGA_MQ_PASSWORD}
+CEGA_MQ_VHOST = ${CEGA_MQ_VHOST}
#
-CEGA_MQ_USER = ${CEGA_MQ_USER}
-CEGA_MQ_PASSWORD = ${CEGA_MQ_PASSWORD}
-CEGA_MQ_VHOST = ${CEGA_MQ_VHOST}
+CEGA_ENDPOINT = http://cega_users/user/%s
+CEGA_ENDPOINT_RESP_PASSWD = .password_hash
+CEGA_ENDPOINT_RESP_PUBKEY = .pubkey
+LEGA_SWE1_PASSWORD = ${LEGA_SWE1_PASSWORD}
+LEGA_FIN1_PASSWORD = ${LEGA_FIN1_PASSWORD}
EOF
[[ $VERBOSE == 'yes' ]] && cat $ABS_PRIVATE/.trace
diff --git a/docker/ega.yml b/docker/ega.yml
index 56618d7f..b2e9f772 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -39,17 +39,37 @@ services:
command: frontend.sh
# SFTP inbox
- inbox:
+ inbox_swe1:
build: images/inbox
hostname: ega_inbox
depends_on:
- db
env_file:
- .env.d/db
- - .env.d/cega
+ - .env.d/cega.swe1
ports:
- "2222:22"
- container_name: ega_inbox
+ container_name: ega_inbox_swe1
+ image: nbis/ega:inbox
+ volumes:
+ - ${CONF}:/etc/ega/conf.ini:ro
+ - ${CODE}:/root/ega
+ - inbox:/ega/inbox
+ - ${ENTRYPOINTS}/inbox.sh:/usr/local/bin/inbox.sh:ro
+ command: inbox.sh
+
+ # SFTP inbox
+ inbox_fin1:
+ build: images/inbox
+ hostname: ega_inbox
+ depends_on:
+ - db
+ env_file:
+ - .env.d/db
+ - .env.d/cega.fin1
+ ports:
+ - "2223:22"
+ container_name: ega_inbox_fin1
image: nbis/ega:inbox
volumes:
- ${CONF}:/etc/ega/conf.ini:ro
@@ -64,7 +84,7 @@ services:
depends_on:
- db
- mq
- - inbox
+ - inbox_swe1
hostname: ega_vault
container_name: ega_vault
image: nbis/ega:common
@@ -83,7 +103,7 @@ services:
- db
- mq
- keys
- - inbox
+ - inbox_swe1
image: nbis/ega:worker
environment:
- GPG_TTY=/dev/console
@@ -152,6 +172,7 @@ services:
- ${CEGA_MQ_DEFS}:/etc/rabbitmq/defs.json:ro
cega_users:
+ env_file: .env.d/cega_instances
build: images/cega_users
image: nbis/ega:cega_users
container_name: cega_users
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index 4dccdd44..0c63d7da 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -55,5 +55,8 @@ EOF
chmod 750 /usr/local/bin/ega_ssh_keys.sh
chgrp ega /usr/local/bin/ega_ssh_keys.sh
+# Greetings per site
+[[ -z "${LEGA_INSTANCE_GREETING}" ]] || echo ${LEGA_INSTANCE_GREETING} > /ega/banner
+
echo "Starting the SFTP server"
exec /usr/sbin/sshd -D -e
diff --git a/docker/images/cega_users/Dockerfile b/docker/images/cega_users/Dockerfile
index 6e0cf085..55a33947 100644
--- a/docker/images/cega_users/Dockerfile
+++ b/docker/images/cega_users/Dockerfile
@@ -1,7 +1,6 @@
FROM nbis/ega:common
LABEL maintainer "Frédéric Haziza, NBIS"
-
##################################
RUN mkdir /cega
VOLUME /cega/users
diff --git a/docker/images/cega_users/server.py b/docker/images/cega_users/server.py
index 07a687c6..f3012772 100644
--- a/docker/images/cega_users/server.py
+++ b/docker/images/cega_users/server.py
@@ -9,10 +9,13 @@
'''
import sys
+import os
import asyncio
import ssl
import yaml
from pathlib import Path
+from functools import wraps
+from base64 import b64decode
from aiohttp import web
import jinja2
@@ -21,25 +24,50 @@
# For the match, we turn that off
ssl.match_hostname = lambda cert, hostname: True
+instances = {}
+for instance in os.environ.get('LEGA_INSTANCES','').strip().split(','):
+ instances[instance] = (Path(f'/cega/users/{instance.lower()}'), os.environ[f'LEGA_{instance}_PASSWORD'])
+
+def protected(func):
+ @wraps(func)
+ def wrapped(request):
+ auth_header = request.headers.get('AUTHORIZATION')
+ if not auth_header:
+ raise web.HTTPUnauthorized(text=f'Protected access\n')
+ _, token = auth_header.split(None, 1) # Skipping the Basic keyword
+ instance,passwd = b64decode(token).decode().split(':', 1)
+ info = instances.get(instance)
+ if info is not None and info[1] == passwd:
+ request.match_info['lega'] = instance
+ request.match_info['users_dir'] = info[0]
+ return func(request)
+ raise web.HTTPUnauthorized(text=f'Protected access\n')
+ return wrapped
+
+
@aiohttp_jinja2.template('users.html')
async def index(request):
- users_dir = Path('/cega/users')
- files = [f for f in users_dir.iterdir() if f.is_file()]
- users = {}
- for f in files:
- with open(f, 'r') as stream:
- users[f.stem] = yaml.load(stream)
- return { "users": users }
-
+ users={}
+ for instance, (users_dir, _) in instances.items():
+ users[instance]= {}
+ files = [f for f in users_dir.iterdir() if f.is_file()]
+ for f in files:
+ with open(f, 'r') as stream:
+ users[instance][f.stem] = yaml.load(stream)
+ return { "cega_users": users }
+
+@protected
async def user(request):
name = request.match_info['id']
+ lega_instance = request.match_info['lega']
+ users_dir = request.match_info['users_dir']
try:
- with open(f'/cega/users/{name}.yml', 'r') as stream:
+ with open(f'{users_dir}/{name}.yml', 'r') as stream:
d = yaml.load(stream)
json_data = { 'password_hash': d.get("password_hash",None), 'pubkey': d.get("pubkey",None), 'expiration': d.get("expiration",None) }
return web.json_response(json_data)
except OSError:
- raise web.HTTPBadRequest(text=f'No info for that user {name}... yet\n')
+ raise web.HTTPBadRequest(text=f'No info for that user {name} in LocalEGA {lega_instance}... yet\n')
def main():
diff --git a/docker/images/cega_users/users.html b/docker/images/cega_users/users.html
index 67b52475..51141526 100644
--- a/docker/images/cega_users/users.html
+++ b/docker/images/cega_users/users.html
@@ -7,19 +7,25 @@
em { display:inline-block; min-width:10em; text-align:right; }
em:after { content:":"; display:inline-block; margin:0 1em; font-style: normal; }
span { display:inline-block; max-width:60em; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
+ h1 { text.aligned: center; }
+ h2 { padding-left:2em; background:black; color:white; }
+ dt { font-weight: bold; font-variant: small-caps; border-top:1px solid black; margin-top:1em; padding-top:0.5em; }
+ dt:first-child { border-top:none; margin-top:0; padding-top:0; }
Central EGA Users
- {% for username, data in users.items() %}
-
+ {% for instance, lega_users in cega_users.items() %}
+ {{ instance }}
- - {{username}}
+ {% for username, data in lega_users.items() %}
+ - {{ username }}
- password_hash{{ data['password_hash'] }}
- pubkey{{ data['pubkey'] }}
- expiration{{ data['expiration'] }}
-
+ {% endfor %}
+
{% endfor %}
diff --git a/docker/images/db/db.sql b/docker/images/db/db.sql
index 292e6f15..8a2e88fc 100644
--- a/docker/images/db/db.sql
+++ b/docker/images/db/db.sql
@@ -1,5 +1,5 @@
-DROP DATABASE IF EXISTS lega;
-CREATE DATABASE lega;
+-- DROP DATABASE IF EXISTS lega;
+-- CREATE DATABASE lega;
\connect lega
diff --git a/docker/images/inbox/banner b/docker/images/inbox/banner
index 0e05dc3c..ce1c541d 100644
--- a/docker/images/inbox/banner
+++ b/docker/images/inbox/banner
@@ -1 +1 @@
-Welcome to Local EGA (Sweden)
+Welcome to Local EGA
diff --git a/src/auth/backend.c b/src/auth/backend.c
index 2bfd02a9..09244608 100644
--- a/src/auth/backend.c
+++ b/src/auth/backend.c
@@ -215,7 +215,7 @@ backend_get_userentry(const char *username,
/* if REST disabled */
if(!options->with_rest){
- D("contacting cega for user: %s is disabled\n", username);
+ D("Contacting cega for user %s is disabled\n", username);
return NSS_STATUS_NOTFOUND;
}
diff --git a/src/auth/cega.c b/src/auth/cega.c
index 1c19d670..b18ca9a0 100644
--- a/src/auth/cega.c
+++ b/src/auth/cega.c
@@ -83,11 +83,12 @@ fetch_from_cega(const char *username, char **buffer, size_t *buflen, int *errnop
const char *pwd = NULL;
const char *pbk = NULL;
- /* enum json_tokener_error jerr = json_tokener_success; */
- /* json_object *pwdh = NULL, *pubkey = NULL; */
- /* json_object *json = NULL, *json_response = NULL, *json_result = NULL, *jobj = NULL; */
+ D("Contacting cega for user: %s\n", username);
- D("contacting cega for user: %s\n", username);
+ if(!options->rest_user || !options->rest_password){
+ D("Empty CEGA credentials\n");
+ return false; /* early quit */
+ }
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
From f2997835c8f6fb1bb2d4bea3add0ee1bf5299948 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 01:29:56 +0100
Subject: [PATCH 052/528] Better separation between LocalEGA instances
---
docker/README.md | 9 +-
docker/bootstrap/README.md | 16 +-
docker/bootstrap/boot.sh | 9 +
docker/bootstrap/cega.sh | 272 ++++++++++++++++++++++++++
docker/bootstrap/defaults/cega | 17 ++
docker/bootstrap/defaults/fin1 | 17 ++
docker/bootstrap/defaults/swe1 | 15 ++
docker/bootstrap/generate.sh | 299 +++++------------------------
docker/bootstrap/lib.sh | 35 ++++
docker/bootstrap/populate.sh | 30 ++-
docker/ega.yml | 133 +++++++------
docker/entrypoints/inbox.sh | 8 +-
docker/images/cega_users/server.py | 2 +-
13 files changed, 528 insertions(+), 334 deletions(-)
create mode 100755 docker/bootstrap/boot.sh
create mode 100755 docker/bootstrap/cega.sh
create mode 100644 docker/bootstrap/defaults/cega
create mode 100644 docker/bootstrap/defaults/fin1
create mode 100644 docker/bootstrap/defaults/swe1
create mode 100644 docker/bootstrap/lib.sh
diff --git a/docker/README.md b/docker/README.md
index ddf61983..39bfd5c8 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -6,18 +6,17 @@ First [create the EGA docker images](images) beforehand, with `make -C images`.
You can then [generate the private data](bootstrap), with either:
- docker run --rm -it -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/generate.sh -f
+ docker run --rm -it -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/boot.sh
-> Note: you can run `bootstrap/generate.sh` on your host machine but
+> Note: you can run `bootstrap/{cega,generate}.sh` on your host machine but
> you need the required tools installed, including Python 3.6, GnuPG
> 2.2.1, OpenSSL, `readlink`, `xxd`, ...
You can afterwards copy the settings into place with
- bootstrap/populate.sh
+ bootstrap/populate.sh -f
-The passwords are in `bootstrap/private/.trace` and the errors (if
-any) are in `bootstrap/.err`.
+The passwords are in `bootstrap/private/.trace.*` and the errors (if any) are in `bootstrap/.err`.
Alternatively, you can setup all [configuration files by hand](bootstrap/yourself.md).
diff --git a/docker/bootstrap/README.md b/docker/bootstrap/README.md
index 3233cbb6..8743f4ee 100644
--- a/docker/bootstrap/README.md
+++ b/docker/bootstrap/README.md
@@ -11,15 +11,15 @@ We create a separate folder and generate all the necessary files in it (require
GnuPG 2.2.1, OpenSSL 1.0.2 and Python 3.6.1). Note that potential error
messages can be found at the file `.err` in the same folder.
- ./generate.sh
+ ./cega.sh
+ ./generate.sh --
We then move the `.env` and `.env.d/` into place (backing them up in the
destination location if there was already a version)
./populate.sh
-The passwords are in `private/.trace` (if you did not use
-`--private_dir`)
+The passwords are in `private/.trace.*` (if you did not use `--private_dir`)
If you don't have the required tools installed on your machine (namely
GnuPG 2.2.1, OpenSSL 1.0.2 and Python 3.6.1), you can use the `nbis/ega:worker`
@@ -27,7 +27,7 @@ image that you have built up with the `make` command in the [images](../images)
In the same folder as `generate.sh`, run
- docker run --rm -it -v ${PWD}:/ega nbis/ega:worker /ega/generate.sh -f
+ docker run --rm -it -v ${PWD}:/ega nbis/ega:worker /ega/generate.sh -f -- swe1
That will create a folder, named 'private', with all the settings
After that, you can run `./populate.sh` to move the `.env` and `.env.d/` into
@@ -41,10 +41,10 @@ different PATHs in the `.env` and `.env.d` settings.
## Troubleshooting
-* If the command `./generate.sh` takes more than a few seconds to run, it is
- usually because your computer does not have enough entropy. You can use the
- program `rng-tools` to solve this problem. E.g. on Debian/Ubuntu system,
- install the software by
+* If the commands `./cega.sh` and `./generate.sh` take more than a
+ few seconds to run, it is usually because your computer does not
+ have enough entropy. You can use the program `rng-tools` to solve
+ this problem. E.g. on Debian/Ubuntu system, install the software by
sudo apt-get install rng-tools
diff --git a/docker/bootstrap/boot.sh b/docker/bootstrap/boot.sh
new file mode 100755
index 00000000..4906939e
--- /dev/null
+++ b/docker/bootstrap/boot.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+set -e
+
+SCRIPT=$(dirname ${BASH_SOURCE[0]})
+HERE=$PWD/${SCRIPT#./}
+
+$HERE/cega.sh -f
+$HERE/generate.sh -f -- swe1
+$HERE/generate.sh -f -- fin1
diff --git a/docker/bootstrap/cega.sh b/docker/bootstrap/cega.sh
new file mode 100755
index 00000000..36a0dba7
--- /dev/null
+++ b/docker/bootstrap/cega.sh
@@ -0,0 +1,272 @@
+#!/usr/bin/env bash
+set -e
+
+SCRIPT=$(dirname ${BASH_SOURCE[0]})
+HERE=$PWD/${SCRIPT#./}
+
+source $HERE/lib.sh
+
+# Defaults
+VERBOSE=yes
+FORCE=no
+PRIVATE=private
+DEFAULTS=$HERE/defaults/cega
+
+function usage {
+ echo "Usage: $0 [options] -- "
+ echo -e "\nOptions are:"
+ echo -e "\t--private_dir \tName of the main folder for private data"
+ echo -e "\t--force, -f \tForce the re-creation of the subfolders"
+ echo ""
+ echo -e "\t--defaults \tDefaults data to be loaded [$DEFAULTS]"
+ echo ""
+ echo -e "\t--quiet, -q \tRemoves the verbose output (and uses -f)"
+ echo -e "\t--help, -h \tOutputs this message and exits"
+ echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
+ echo ""
+}
+
+# While there are arguments or '--' is reached
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --quiet|-q) VERBOSE=no;;
+ --help|-h) usage; exit 0;;
+ --force|-f) FORCE=yes;;
+ --private_dir) PRIVATE=$2; shift;;
+ --defaults) DEFAULTS=$2; shift;;
+ --) shift; break;;
+ *) echo "$0: error - unrecognized option $1" 1>&2; usage; exit 1;;
+ esac
+ shift
+done
+
+if [[ -e $DEFAULTS ]];then
+ source $DEFAULTS
+else
+ echo "Defaults not found"
+ exit 1
+fi
+
+[[ $VERBOSE == 'no' ]] && exec 1>${HERE}/.log && FORCE='yes'
+exec 2>${HERE}/.err
+
+case $PRIVATE in
+ /*) ABS_PRIVATE=$PRIVATE;;
+ ./*|../*) ABS_PRIVATE=$PWD/$PRIVATE;;
+ *) ABS_PRIVATE=$HERE/$PRIVATE;;
+esac
+
+[[ -x $(readlink ${OPENSSL}) ]] && echo "${OPENSSL} is not executable" && exit 3
+
+#########################################################################
+# And....cue music
+#########################################################################
+
+rm_politely $ABS_PRIVATE/cega
+mkdir -p $ABS_PRIVATE/cega/{users,mq}
+
+echo "Generating data for a fake Central EGA"
+
+echo -e "\t* fake EGA users"
+
+EGA_USER_PASSWORD_JOHN=$(generate_password 16)
+EGA_USER_PASSWORD_JANE=$(generate_password 16)
+EGA_USER_PASSWORD_TAYLOR=$(generate_password 16)
+
+EGA_USER_PUBKEY_JOHN=$ABS_PRIVATE/cega/users/john.pub
+EGA_USER_SECKEY_JOHN=$ABS_PRIVATE/cega/users/john.sec
+
+EGA_USER_PUBKEY_JANE=$ABS_PRIVATE/cega/users/jane.pub
+EGA_USER_SECKEY_JANE=$ABS_PRIVATE/cega/users/jane.sec
+
+
+${OPENSSL} genrsa -out ${EGA_USER_SECKEY_JOHN} -passout pass:${EGA_USER_PASSWORD_JOHN} 2048
+${OPENSSL} rsa -in ${EGA_USER_SECKEY_JOHN} -passin pass:${EGA_USER_PASSWORD_JOHN} -pubout -out ${EGA_USER_PUBKEY_JOHN}
+chmod 400 ${EGA_USER_SECKEY_JOHN}
+
+${OPENSSL} genrsa -out ${EGA_USER_SECKEY_JANE} -passout pass:${EGA_USER_PASSWORD_JANE} 2048
+${OPENSSL} rsa -in ${EGA_USER_SECKEY_JANE} -passin pass:${EGA_USER_PASSWORD_JANE} -pubout -out ${EGA_USER_PUBKEY_JANE}
+chmod 400 ${EGA_USER_SECKEY_JANE}
+
+
+cat > $ABS_PRIVATE/cega/users/john.yml < $ABS_PRIVATE/cega/users/jane.yml < $ABS_PRIVATE/cega/users/taylor.yml < /dev/null
+ln -s ../john.yml .
+ln -s ../jane.yml .
+ln -s ../taylor.yml .
+popd > /dev/null
+# John has also access to FIN1
+pushd $ABS_PRIVATE/cega/users/fin1 > /dev/null
+ln -s ../john.yml .
+popd > /dev/null
+
+#########################################################################
+
+# Note: We could use a .env.d/cega_mq file with
+# RABBITMQ_DEFAULT_USER=...
+# RABBITMQ_DEFAULT_PASSWORD=...
+# RABBITMQ_DEFAULT_VHOST=...
+# But then the queues and bindings are not properly set up
+# Doing this instead:
+
+echo -e "\t* a CEGA password for the MQ"
+function rabbitmq_hash {
+ # 1) Generate a random 32 bit salt
+ # 2) Concatenate that with the UTF-8 representation of the password
+ # 3) Take the SHA-256 hash
+ # 4) Concatenate the salt again
+ # 5) Convert to base64 encoding
+ local SALT=${2:-$(${OPENSSL} rand -hex 4)}
+ (
+ printf $SALT | xxd -p -r
+ ( printf $SALT | xxd -p -r; printf $1 ) | ${OPENSSL} dgst -binary -sha256
+ ) | base64
+}
+
+function output_password_hashes {
+ declare -a tmp
+ for i in "${!CEGA_MQ[@]}"; do
+ tmp+=("{\"name\":\"cega_$i\",\"password_hash\":\"$(rabbitmq_hash ${CEGA_MQ[$i]})\",\"hashing_algorithm\":\"rabbit_password_hashing_sha256\",\"tags\":\"administrator\"}")
+ done
+ join_by ",\n" "${tmp[@]}"
+}
+
+function output_vhosts {
+ declare -a tmp
+ for i in "${!CEGA_MQ[@]}"; do
+ tmp+=("{\"name\":\"$i\"}")
+ done
+ join_by "," "${tmp[@]}"
+}
+
+function output_permissions {
+ declare -a tmp
+ for i in "${!CEGA_MQ[@]}"; do
+ tmp+=("{\"user\":\"cega_$i\", \"vhost\":\"$i\", \"configure\":\".*\", \"write\":\".*\", \"read\":\".*\"}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+function output_queues {
+ declare -a tmp
+ for i in "${!CEGA_MQ[@]}"; do
+ tmp+=("{\"name\":\"$i.v1.commands.file\", \"vhost\":\"$i\", \"durable\":true, \"auto_delete\":false, \"arguments\":{}}")
+ tmp+=("{\"name\":\"$i.v1.commands.completed\", \"vhost\":\"$i\", \"durable\":true, \"auto_delete\":false, \"arguments\":{}}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+function output_exchanges {
+ declare -a tmp
+ for i in "${!CEGA_MQ[@]}"; do
+ tmp+=("{\"name\":\"localega.v1\", \"vhost\":\"$i\", \"type\":\"topic\", \"durable\":true, \"auto_delete\":false, \"internal\":false, \"arguments\":{}}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+
+function output_bindings {
+ declare -a tmp
+ for i in "${!CEGA_MQ[@]}"; do
+ tmp+=("{\"source\":\"localega.v1\",\"vhost\":\"$i\",\"destination_type\":\"queue\",\"arguments\":{},\"destination\":\"$i.v1.commands.file\",\"routing_key\":\"$i.file\"}")
+ tmp+=("{\"source\":\"localega.v1\",\"vhost\":\"$i\",\"destination_type\":\"queue\",\"arguments\":{},\"destination\":\"$i.v1.commands.completed\",\"routing_key\":\"$i.completed\"}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+cat > $ABS_PRIVATE/cega/mq/defs.json < $ABS_PRIVATE/.env.d/cega_instances
+for i in "${!CEGA_REST[@]}"; do
+ tmp=CEGA_REST_${i}_PASSWORD
+ echo "${tmp}=${CEGA_REST[$i]}" >> $ABS_PRIVATE/.env.d/cega_instances
+done
+
+for i in "${!CEGA_REST[@]}"; do
+ mkdir $ABS_PRIVATE/.env.d/$i
+ cat > $ABS_PRIVATE/.env.d/$i/cega < Generation completed for CentralEGA \xF0\x9F\x91\x8D\n"
+
+{
+ cat </$PRIVATE/cega/users/john.pub
+EGA_USER_PUBKEY_JANE = /$PRIVATE/cega/users/jane.pub
+EGA_USER_PASSWORD_TAYLOR = ${EGA_USER_PASSWORD_TAYLOR}
+# =============================
+EOF
+
+ for i in "${!CEGA_MQ[@]}"; do
+ echo -e "CEGA_MQ_${i}_PASSWORD = ${CEGA_MQ[$i]}"
+ done
+ echo -e "# ============================="
+ for i in "${!CEGA_REST[@]}"; do
+ echo -e "CEGA_REST_${i}_PASSWORD = ${CEGA_REST[$i]}"
+ done
+
+ for i in "${!CEGA_REST[@]}"; do
+ echo "# ============================="
+ echo "CEGA_ENDPOINT for $i"
+ echo "# ============================="
+ cat $ABS_PRIVATE/.env.d/$i/cega
+ done
+} > $ABS_PRIVATE/.trace.cega
+[[ $VERBOSE == 'yes' ]] && cat $ABS_PRIVATE/.trace.cega
diff --git a/docker/bootstrap/defaults/cega b/docker/bootstrap/defaults/cega
new file mode 100644
index 00000000..e0cff552
--- /dev/null
+++ b/docker/bootstrap/defaults/cega
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+set -e
+
+OPENSSL=openssl
+LEGA_INSTANCES="swe1,fin1"
+
+declare -A CEGA_MQ
+CEGA_MQ['swe1']=$(generate_password 16)
+CEGA_MQ['fin1']=$(generate_password 16)
+
+declare -A CEGA_REST
+CEGA_REST['swe1']=$(generate_password 16)
+CEGA_REST['fin1']=$(generate_password 16)
+
+declare -A LEGA_GREETINGS
+LEGA_GREETINGS['swe1']="Welcome to Local EGA Sweden @ NBIS"
+LEGA_GREETINGS['fin1']="Welcome to Local EGA Finland @ CSC"
diff --git a/docker/bootstrap/defaults/fin1 b/docker/bootstrap/defaults/fin1
new file mode 100644
index 00000000..40ef28d0
--- /dev/null
+++ b/docker/bootstrap/defaults/fin1
@@ -0,0 +1,17 @@
+GPG=gpg
+OPENSSL=openssl
+
+SSL_SUBJ="/C=FI/ST=Finland/L=Helsinki/O=CSC/OU=SysDevs/CN=LocalEGA/emailAddress=ega@csc.fi"
+
+DB_USER=lega
+DB_PASSWORD=$(generate_password 16)
+DB_TRY=30
+
+GPG_NAME="EGA Finland"
+GPG_COMMENT="@CSC"
+GPG_EMAIL="ega@csc.fi"
+
+GPG_PASSPHRASE=$(generate_password 16)
+RSA_PASSPHRASE=$(generate_password 16)
+
+
diff --git a/docker/bootstrap/defaults/swe1 b/docker/bootstrap/defaults/swe1
new file mode 100644
index 00000000..85a21800
--- /dev/null
+++ b/docker/bootstrap/defaults/swe1
@@ -0,0 +1,15 @@
+GPG=gpg
+OPENSSL=openssl
+
+SSL_SUBJ="/C=SE/ST=Sweden/L=Uppsala/O=NBIS/OU=SysDevs/CN=LocalEGA/emailAddress=ega@nbis.se"
+
+DB_USER=lega
+DB_PASSWORD=$(generate_password 16)
+DB_TRY=30
+
+GPG_NAME="EGA Sweden"
+GPG_COMMENT="@NBIS"
+GPG_EMAIL="ega@nbis.se"
+
+GPG_PASSPHRASE=$(generate_password 16)
+RSA_PASSPHRASE=$(generate_password 16)
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index e95434cf..92e15a68 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -4,52 +4,19 @@ set -e
SCRIPT=$(dirname ${BASH_SOURCE[0]})
HERE=$PWD/${SCRIPT#./}
-# Defaults:
+source $HERE/lib.sh
+
+# Defaults
VERBOSE=yes
FORCE=no
-SSL_SUBJ="/C=SE/ST=Sweden/L=Uppsala/O=NBIS/OU=SysDevs/CN=LocalEGA/emailAddress=ega@nbis.se"
PRIVATE=private
-DB_USER=lega
-DB_TRY=30
-CEGA_MQ_USER=cega_sweden
-CEGA_MQ_VHOST=se
-
-GPG=gpg
-GPG_NAME="EGA Sweden"
-GPG_COMMENT="@NBIS"
-GPG_EMAIL="ega@nbis.se"
-
-OPENSSL=openssl
function usage {
- echo "Usage: $0 [options]"
+ echo "Usage: $0 [options] -- "
echo -e "\nOptions are:"
echo -e "\t--private_dir \tName of the main folder for private data"
echo -e "\t--force, -f \tForce the re-creation of the subfolders"
echo ""
- echo -e "\t--gpg_exec \tgpg executable"
- echo -e "\t--openssl \topenssl executable"
- echo ""
- echo -e "\t--gpg_passphrase \tPassphrase at the GPG key creation"
- echo -e "\t--gpg_name ,"
- echo -e "\t--gpg_comment ,"
- echo -e "\t--gpg_email \tDetails for the GPG key"
- echo ""
- echo -e "\t--rsa_passphrase \tPassphrase at the RSA key creation"
- echo ""
- echo -e "\t--ssl_subj \tSubject for the SSL certificates"
- echo -e "\t \t[Default: ${SSL_SUBJ}]"
- echo ""
- echo -e "\t--db_user ,"
- echo -e "\t--db_password \tDatabase username and password"
- echo -e "\t--db_try \tDatabase connection attempts"
- echo -e "\t \t[User default: ${DB_USER} | Connection attempts default: ${DB_TRY}]"
- echo -e ""
- echo -e "\t--cega_mq_user ,"
- echo -e "\t--cega_mq_password ,"
- echo -e "\t--cega_mq_vhost , \tUsername, password, vhost for the Central EGA message broker"
- echo -e "\t \t[User default: ${CEGA_MQ_USER}, VHost default: ${CEGA_MQ_VHOST}]"
- echo ""
echo -e "\t--quiet, -q \tRemoves the verbose output (and uses -f)"
echo -e "\t--help, -h \tOutputs this message and exits"
echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
@@ -63,26 +30,23 @@ while [[ $# -gt 0 ]]; do
--help|-h) usage; exit 0;;
--force|-f) FORCE=yes;;
--private_dir) PRIVATE=$2; shift;;
- --gpg_passphrase) GPG_PASSPHRASE=$2; shift;;
- --gpg_name) GPG_NAME=$2; shift;;
- --gpg_comment) GPG_COMMENT=$2; shift;;
- --gpg_email) GPG_EMAIL=$2; shift;;
- --gpg_exec) GPG=$2; shift;;
- --openssl) OPENSSL=$2; shift;;
- --rsa_passphrase) RSA_PASSPHRASE=$2; shift;;
- --ssl_subj) SSL_SUBJ=$2; shift;;
- --db_user) DB_USER=$2; shift;;
- --db_password) DB_PASSWORD=$2; shift;;
- --db_try) DB_TRY=$2; shift;;
- --cega_mq_user) CEGA_MQ_USER=$2; shift;;
- --cega_mq_password) CEGA_MQ_PASSWORD=$2; shift;;
- --cega_mq_vhost) CEGA_MQ_VHOST=$2; shift;;
--) shift; break;;
*) echo "$0: error - unrecognized option $1" 1>&2; usage; exit 1;;
esac
shift
done
+# Loading the instance's settings
+INSTANCE=$1
+[[ -z ${INSTANCE} ]] && usage && exit 1
+
+if [[ -f $HERE/defaults/$INSTANCE ]]; then
+ source $HERE/defaults/$INSTANCE
+else
+ echo "No settings found for $INSTANCE"
+ exit 1
+fi
+
[[ $VERBOSE == 'no' ]] && exec 1>${HERE}/.log && FORCE='yes'
exec 2>${HERE}/.err
@@ -94,63 +58,26 @@ if [ -z "${DB_USER}" -o "${DB_USER}" == "postgres" ]; then
exit 4
fi
-#########################################################################
-# Creating the necessary folders
-# Ask recreate them if already existing
-#########################################################################
-
case $PRIVATE in
/*) ABS_PRIVATE=$PRIVATE;;
./*|../*) ABS_PRIVATE=$PWD/$PRIVATE;;
*) ABS_PRIVATE=$HERE/$PRIVATE;;
esac
-if [[ -d $ABS_PRIVATE ]]; then
- if [[ $FORCE == 'yes' ]]; then
- rm -rf $ABS_PRIVATE
- else
- # Asking
- echo "[Warning] The folder \"$ABS_PRIVATE\" already exists. "
- while : ; do # while = In a subshell
- echo -n "[Warning] "
- echo -n -e "Proceed to re-create it? [y/N] "
- read -t 10 yn
- case $yn in
- y) rm -rf $ABS_PRIVATE; break;;
- N) echo "Ok. Choose another private directory. Exiting"; exit 1;;
- *) echo "Eh?";;
- esac
- done
- fi
-fi
-
-mkdir -p $ABS_PRIVATE/{gpg,rsa,certs,cega/users,cega/mq,.env.d}
+[[ ! -f $ABS_PRIVATE/.trace.cega ]] && echo "You must run $HERE/cega.sh first" && exit 1
#########################################################################
-# Generating the non-supplied values
+# And....cue music
#########################################################################
-function generate_password {
- local size=${1:-16} # defaults to 16 characters
- p=$(python3.6 -c "import secrets,string;print(''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(${size})))")
- echo $p
-}
-
-[[ -z $GPG_PASSPHRASE ]] && GPG_PASSPHRASE=$(generate_password 16)
-[[ -z $RSA_PASSPHRASE ]] && RSA_PASSPHRASE=$(generate_password 16)
-[[ -z $DB_PASSWORD ]] && DB_PASSWORD=$(generate_password 16)
-[[ -z $CEGA_MQ_PASSWORD ]] && CEGA_MQ_PASSWORD=$(generate_password 16)
-
-LEGA_SWE1_PASSWORD=$(generate_password 16)
-LEGA_FIN1_PASSWORD=$(generate_password 16)
+rm_politely $ABS_PRIVATE/$INSTANCE
+mkdir -p $ABS_PRIVATE/$INSTANCE/{gpg,rsa,certs}
-#########################################################################
-# And....cue music
-#########################################################################
+echo "Generating private data for ${INSTANCE^^}"
-echo -e "\nGenerating the GnuPG key"
+echo -e "\t* the GnuPG key"
-cat > $ABS_PRIVATE/gen_key < $ABS_PRIVATE/$INSTANCE/gen_key < $ABS_PRIVATE/cega/users/john.yml < $ABS_PRIVATE/cega/users/jane.yml < $ABS_PRIVATE/cega/users/taylor.yml < $ABS_PRIVATE/keys.conf < $ABS_PRIVATE/$INSTANCE/keys.conf < $ABS_PRIVATE/ega.conf < $ABS_PRIVATE/$INSTANCE/ega.conf < $ABS_PRIVATE/cega/mq/defs.json < $ABS_PRIVATE/.env.d/db < $ABS_PRIVATE/.env.d/$INSTANCE/db < $ABS_PRIVATE/.env.d/gpg < $ABS_PRIVATE/.env.d/$INSTANCE/gpg < $ABS_PRIVATE/.env.d/cega_instances < $ABS_PRIVATE/.env.d/cega.swe1 < $ABS_PRIVATE/.env.d/cega.fin1 < /dev/null
-ln -s ../john.yml .
-ln -s ../jane.yml .
-ln -s ../taylor.yml .
-popd > /dev/null
-# John has also access to FIN1
-pushd $ABS_PRIVATE/cega/users/fin1 > /dev/null
-ln -s ../john.yml .
-popd > /dev/null
#########################################################################
-echo -e "\tGeneration completed" $'\xF0\x9F\x91\x8D'
+echo -e "\n=> Generation completed for ${INSTANCE^^} \xF0\x9F\x91\x8D\n"
+
-cat > $ABS_PRIVATE/.trace < $ABS_PRIVATE/.trace.$INSTANCE </$PRIVATE/cega/users/john.pub
-EGA_USER_PUBKEY_JANE = /$PRIVATE/cega/users/jane.pub
-EGA_USER_PASSWORD_TAYLOR = ${EGA_USER_PASSWORD_TAYLOR}
-#
-CEGA_MQ_USER = ${CEGA_MQ_USER}
-CEGA_MQ_PASSWORD = ${CEGA_MQ_PASSWORD}
-CEGA_MQ_VHOST = ${CEGA_MQ_VHOST}
-#
-CEGA_ENDPOINT = http://cega_users/user/%s
-CEGA_ENDPOINT_RESP_PASSWD = .password_hash
-CEGA_ENDPOINT_RESP_PUBKEY = .pubkey
-LEGA_SWE1_PASSWORD = ${LEGA_SWE1_PASSWORD}
-LEGA_FIN1_PASSWORD = ${LEGA_FIN1_PASSWORD}
EOF
-[[ $VERBOSE == 'yes' ]] && cat $ABS_PRIVATE/.trace
+[[ $VERBOSE == 'yes' ]] && cat $ABS_PRIVATE/.trace.$INSTANCE
diff --git a/docker/bootstrap/lib.sh b/docker/bootstrap/lib.sh
new file mode 100644
index 00000000..889eb515
--- /dev/null
+++ b/docker/bootstrap/lib.sh
@@ -0,0 +1,35 @@
+function rm_politely {
+ local FOLDER=$1
+
+ if [[ -d $FOLDER ]]; then
+ if [[ $FORCE == 'yes' ]]; then
+ rm -rf $FOLDER
+ else
+ # Asking
+ echo "[Warning] The folder \"$FOLDER\" already exists. "
+ while : ; do # while = In a subshell
+ echo -n "[Warning] "
+ echo -n -e "Proceed to re-create it? [y/N] "
+ read -t 10 yn
+ case $yn in
+ y) rm -rf $FOLDER; break;;
+ N) echo "Ok. Choose another private directory. Exiting"; exit 1;;
+ *) echo "Eh?";;
+ esac
+ done
+ fi
+ fi
+}
+
+function generate_password {
+ local size=${1:-16} # defaults to 16 characters
+ p=$(python3.6 -c "import secrets,string;print(''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(${size})))")
+ echo $p
+}
+
+
+function print_arr {
+ for x in "${!1[@]}"; do printf "[%s]=%s " "$x" "${array[$x]}" ; done
+}
+
+function join_by { local IFS="$1"; shift; echo -n "$*"; }
diff --git a/docker/bootstrap/populate.sh b/docker/bootstrap/populate.sh
index 418106bd..a0d12e3a 100755
--- a/docker/bootstrap/populate.sh
+++ b/docker/bootstrap/populate.sh
@@ -85,22 +85,34 @@ COMPOSE_PROJECT_NAME=ega
COMPOSE_FILE=ega.yml
CODE=${ABS_SOURCES}
ENTRYPOINTS=${ABS_ENTRYPOINTS}
-CONF=$ABS_PRIVATE/ega.conf
-KEYS=$ABS_PRIVATE/keys.conf
-SSL_CERT=$ABS_PRIVATE/certs/ssl.cert
-SSL_KEY=$ABS_PRIVATE/certs/ssl.key
-RSA_SEC=$ABS_PRIVATE/rsa/ega.sec
-RSA_PUB=$ABS_PRIVATE/rsa/ega.pub
-GPG_HOME=$ABS_PRIVATE/gpg
+#
CEGA_USERS=$ABS_PRIVATE/cega/users
CEGA_MQ_DEFS=$ABS_PRIVATE/cega/mq/defs.json
EOF
+eval $(grep LEGA_INSTANCES $HERE/defaults/cega)
+
+INSTANCES=(${LEGA_INSTANCES/,/ }) # make it an array
+
+for INSTANCE in "${INSTANCES[@]}"; do
+ cat >> $HERE/../.env <;$HERE;" $ABS_PRIVATE/.trace
+if [[ -f $ABS_PRIVATE/.trace.cega ]]; then
+ sed -i -e "s;;$HERE;" $ABS_PRIVATE/.trace.cega
fi
echomsg "docker-compose configuration files populated"
diff --git a/docker/ega.yml b/docker/ega.yml
index b2e9f772..2c6c6b07 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -3,145 +3,151 @@ version: '3.2'
services:
# Local Message broker
- mq:
- #env_file: .env.d/mq
+ mq_swe1:
+ #env_file: .env.d/swe1/mq
build: images/mq
hostname: ega_mq
ports:
- "15672:15672"
image: nbis/ega:mq
- container_name: ega_mq
+ container_name: ega_mq_swe1
- # Postgres Database
- db:
- env_file: .env.d/db
+ # Postgres Database for Sweden
+ db_swe1:
+ env_file: .env.d/swe1/db
build: images/db
- hostname: ega_db
- container_name: ega_db
+ hostname: ega_db_swe1
+ container_name: ega_db_swe1
+ image: nbis/ega:db
+
+ # Postgres Database for Finland
+ db_fin1:
+ env_file: .env.d/fin1/db
+ build: images/db
+ hostname: ega_db_fin1
+ container_name: ega_db_fin1
image: nbis/ega:db
# ReST frontend
- frontend:
+ frontend_swe1:
build: images/common
hostname: ega_frontend
depends_on:
- - db
+ - db_swe1
ports:
- "9000:80"
expose:
- 80
- container_name: ega_frontend
+ container_name: ega_frontend_swe1
image: nbis/ega:common
volumes:
- - ${CONF}:/etc/ega/conf.ini:ro
+ - ${CONF_swe1}:/etc/ega/conf.ini:ro
- ${CODE}:/root/ega
- ${ENTRYPOINTS}/frontend.sh:/usr/local/bin/frontend.sh:ro
command: frontend.sh
- # SFTP inbox
+ # SFTP inbox for Sweden
inbox_swe1:
build: images/inbox
hostname: ega_inbox
depends_on:
- - db
+ - db_swe1
env_file:
- - .env.d/db
- - .env.d/cega.swe1
+ - .env.d/swe1/db
+ - .env.d/swe1/cega
ports:
- "2222:22"
container_name: ega_inbox_swe1
image: nbis/ega:inbox
volumes:
- - ${CONF}:/etc/ega/conf.ini:ro
- ${CODE}:/root/ega
- - inbox:/ega/inbox
+ - inbox_swe1:/ega/inbox
+ - ${CONF_swe1}:/etc/ega/conf.ini:ro
- ${ENTRYPOINTS}/inbox.sh:/usr/local/bin/inbox.sh:ro
- command: inbox.sh
+ command: ["inbox.sh","swe1"]
- # SFTP inbox
+ # SFTP inbox for Finland
inbox_fin1:
build: images/inbox
hostname: ega_inbox
depends_on:
- - db
+ - db_fin1
env_file:
- - .env.d/db
- - .env.d/cega.fin1
+ - .env.d/fin1/db
+ - .env.d/fin1/cega
ports:
- "2223:22"
container_name: ega_inbox_fin1
image: nbis/ega:inbox
volumes:
- - ${CONF}:/etc/ega/conf.ini:ro
- ${CODE}:/root/ega
- - inbox:/ega/inbox
+ - inbox_fin1:/ega/inbox
+ - ${CONF_fin1}:/etc/ega/conf.ini:ro
- ${ENTRYPOINTS}/inbox.sh:/usr/local/bin/inbox.sh:ro
- command: inbox.sh
+ command: ["inbox.sh","fin1"]
# Vault
- vault:
+ vault_swe1:
build: images/common
depends_on:
- - db
- - mq
+ - db_swe1
+ - mq_swe1
- inbox_swe1
hostname: ega_vault
- container_name: ega_vault
+ container_name: ega_vault_swe1
image: nbis/ega:common
volumes:
- - ${CONF}:/etc/ega/conf.ini:ro
- ${CODE}:/root/ega
- - staging:/ega/staging
- - vault:/ega/vault
+ - staging_swe1:/ega/staging
+ - vault_swe1:/ega/vault
+ - ${CONF_swe1}:/etc/ega/conf.ini:ro
- ${ENTRYPOINTS}/vault.sh:/usr/local/bin/vault.sh:ro
command: vault.sh
# Ingestion Workers
- ingest:
+ ingest_swe1:
build: images/worker
depends_on:
- - db
- - mq
- - keys
+ - db_swe1
+ - mq_swe1
+ - keys_swe1
- inbox_swe1
image: nbis/ega:worker
environment:
- GPG_TTY=/dev/console
volumes:
- - ${CONF}:/etc/ega/conf.ini:ro
- ${CODE}:/root/ega
- - inbox:/ega/inbox
- - staging:/ega/staging
- - ${SSL_CERT}:/etc/ega/ssl.cert:ro
- - ${GPG_HOME}/pubring.kbx:/root/.gnupg/pubring.kbx:ro
- - ${GPG_HOME}/trustdb.gpg:/root/.gnupg/trustdb.gpg
+ - inbox_swe1:/ega/inbox
+ - staging_swe1:/ega/staging
+ - ${CONF_swe1}:/etc/ega/conf.ini:ro
+ - ${SSL_CERT_swe1}:/etc/ega/ssl.cert:ro
+ - ${GPG_HOME_swe1}/pubring.kbx:/root/.gnupg/pubring.kbx:ro
+ - ${GPG_HOME_swe1}/trustdb.gpg:/root/.gnupg/trustdb.gpg
- ${ENTRYPOINTS}/ingest.sh:/usr/local/bin/ingest.sh:ro
command: ingest.sh
# Key server
- keys:
- env_file: .env.d/gpg
+ keys_swe1:
+ env_file: .env.d/swe1/gpg
build: images/worker
environment:
- GPG_TTY=/dev/console
- # depends_on:
- # - monitors
- hostname: ega_keys
- container_name: ega_keys
+ hostname: ega_keys_swe1
+ container_name: ega_keys_swe1
image: nbis/ega:worker
tty: true
volumes:
- - ${CONF}:/etc/ega/conf.ini:ro
- - ${KEYS}:/etc/ega/keys.ini:ro
+ - ${CONF_swe1}:/etc/ega/conf.ini:ro
+ - ${KEYS_swe1}:/etc/ega/keys.ini:ro
- ${CODE}:/root/ega
- - ${SSL_CERT}:/etc/ega/ssl.cert:ro
- - ${SSL_KEY}:/etc/ega/ssl.key:ro
- - ${GPG_HOME}/pubring.kbx:/root/.gnupg/pubring.kbx
- - ${GPG_HOME}/trustdb.gpg:/root/.gnupg/trustdb.gpg
- - ${GPG_HOME}/openpgp-revocs.d:/root/.gnupg/openpgp-revocs.d:ro
- - ${GPG_HOME}/private-keys-v1.d:/root/.gnupg/private-keys-v1.d:ro
- - ${RSA_SEC}:/etc/ega/rsa/sec.pem:ro
- - ${RSA_PUB}:/etc/ega/rsa/pub.pem:ro
+ - ${SSL_CERT_swe1}:/etc/ega/ssl.cert:ro
+ - ${SSL_KEY_swe1}:/etc/ega/ssl.key:ro
+ - ${GPG_HOME_swe1}/pubring.kbx:/root/.gnupg/pubring.kbx
+ - ${GPG_HOME_swe1}/trustdb.gpg:/root/.gnupg/trustdb.gpg
+ - ${GPG_HOME_swe1}/openpgp-revocs.d:/root/.gnupg/openpgp-revocs.d:ro
+ - ${GPG_HOME_swe1}/private-keys-v1.d:/root/.gnupg/private-keys-v1.d:ro
+ - ${RSA_SEC_swe1}:/etc/ega/rsa/sec.pem:ro
+ - ${RSA_PUB_swe1}:/etc/ega/rsa/pub.pem:ro
- ${ENTRYPOINTS}/keys.sh:/usr/local/bin/keys.sh:ro
command: keys.sh
@@ -183,6 +189,9 @@ services:
# Use the default driver for volume creation
volumes:
- inbox:
- staging:
- vault:
+ inbox_swe1:
+ staging_swe1:
+ vault_swe1:
+ inbox_fin1:
+ # staging_fin1:
+ # vault_fin1:
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index 0c63d7da..dbf17363 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -2,17 +2,19 @@
set -e
+db_instance=ega_db_$1
+
chown root:ega /ega/inbox
chmod 750 /ega/inbox
chmod g+s /ega/inbox # setgid bit
cp -r /root/ega /root/run
pushd /root/run/auth
-make install clean
+make install #clean
ldconfig -v
popd
-EGA_DB_IP=$(getent hosts ega_db | awk '{ print $1 }')
+EGA_DB_IP=$(getent hosts ${db_instance} | awk '{ print $1 }')
mkdir -p /etc/ega
cat > /etc/ega/auth.conf <
Date: Tue, 7 Nov 2017 11:24:52 +0100
Subject: [PATCH 053/528] Adapting the travis test script
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index fd500bf0..cf1f0908 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,7 +10,7 @@ before_install:
cd docker
docker pull -a nbis/ega
make -C images
- docker run --rm -i -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/generate.sh -f
+ docker run --rm -i -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/boot.sh
bootstrap/populate.sh -f
sudo chown -R $USER .
From d6da2adf4adb643ece668ade98a196a6c71b2d01 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Tue, 7 Nov 2017 12:35:59 +0100
Subject: [PATCH 054/528] Refactoring.
---
.../java/se/nbis/lega/cucumber/Utils.java | 24 ++++++++++++++++++-
.../lega/cucumber/hooks/BeforeAfterHooks.java | 4 ++--
.../lega/cucumber/steps/Authentication.java | 11 +++++++++
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index cdcc3600..5a8204df 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -72,7 +72,7 @@ public String executeDBQuery(String query) throws IOException, InterruptedExcept
}
/**
- * Checks if user exists in the local database.
+ * Checks if the user exists in the local database.
*
* @param user Username.
* @return true
if user exists, false
otherwise.
@@ -84,6 +84,28 @@ public boolean isUserExistInDB(String user) throws IOException, InterruptedExcep
return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
}
+ /**
+ * Removes the user from the local database.
+ *
+ * @param user Username.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public void removeUserFromDB(String user) throws IOException, InterruptedException {
+ executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ }
+
+ /**
+ * Removes the user from the inbox.
+ *
+ * @param user Username.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public void removeUserFromInbox(String user) throws IOException, InterruptedException {
+ executeWithinContainer(findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ }
+
/**
* Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
*
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index b685ff08..aba27ac2 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -39,8 +39,8 @@ public void tearDown() throws IOException, InterruptedException {
Utils utils = context.getUtils();
String user = context.getUser();
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
- utils.executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
- utils.executeWithinContainer(utils.findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ utils.removeUserFromDB(user);
+ utils.removeUserFromInbox(user);
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 7fb7d6f1..57b5dd40 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -5,6 +5,7 @@
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Volume;
+import cucumber.api.PendingException;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
@@ -80,6 +81,16 @@ public Authentication(Context context) {
connect(context);
});
+ When("^inbox is not created for me$", () -> {
+ try {
+ disconnect(context);
+ utils.removeUserFromInbox(context.getUser());
+ connect(context);
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
+
Then("^I am in the local database$", () -> {
try {
Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
From 088afe392d15d521ee864031543d63827d88c506 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 12:37:30 +0100
Subject: [PATCH 055/528] nbisweden/ega images
---
.travis.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index cf1f0908..e589db4b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,7 @@ services:
before_install:
- |
cd docker
- docker pull -a nbis/ega
+ docker pull -a nbisweden/ega
make -C images
docker run --rm -i -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/boot.sh
bootstrap/populate.sh -f
@@ -25,7 +25,7 @@ after_success:
- |
if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
- docker push nbis/ega
+ docker push nbisweden/ega
fi
notifications:
From c8e15bf45deea2ee16d299096c0fdd0816f7bb03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 12:38:48 +0100
Subject: [PATCH 056/528] no after install push
---
.travis.yml | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index e589db4b..4d82cec4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,12 +21,12 @@ script:
- cd ../tests
- mvn test -B
-after_success:
- - |
- if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
- docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
- docker push nbisweden/ega
- fi
+# after_success:
+# - |
+# if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
+# docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
+# docker push nbisweden/ega
+# fi
notifications:
email: false
From 16f3625986ec8ab9b55d78bc18f2dbfe33d4de29 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 13:21:28 +0100
Subject: [PATCH 057/528] No docker-compose build, pushing images to docker hub
instead
---
.travis.yml | 2 +-
docker/ega.yml | 51 +++++++++++++++++++++---------------------
docker/images/Makefile | 12 ++++++++--
3 files changed, 37 insertions(+), 28 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 4d82cec4..3bc2b81e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,7 +10,7 @@ before_install:
cd docker
docker pull -a nbisweden/ega
make -C images
- docker run --rm -i -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/boot.sh
+ docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega:worker /ega/boot.sh
bootstrap/populate.sh -f
sudo chown -R $USER .
diff --git a/docker/ega.yml b/docker/ega.yml
index 2c6c6b07..de499399 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -5,32 +5,32 @@ services:
# Local Message broker
mq_swe1:
#env_file: .env.d/swe1/mq
- build: images/mq
+ #build: images/mq
hostname: ega_mq
ports:
- "15672:15672"
- image: nbis/ega:mq
+ image: nbisweden/ega:mq
container_name: ega_mq_swe1
# Postgres Database for Sweden
db_swe1:
env_file: .env.d/swe1/db
- build: images/db
+ #build: images/db
hostname: ega_db_swe1
container_name: ega_db_swe1
- image: nbis/ega:db
+ image: nbisweden/ega:db
# Postgres Database for Finland
db_fin1:
env_file: .env.d/fin1/db
- build: images/db
+ #build: images/db
hostname: ega_db_fin1
container_name: ega_db_fin1
- image: nbis/ega:db
+ image: nbisweden/ega:db
# ReST frontend
frontend_swe1:
- build: images/common
+ #build: images/common
hostname: ega_frontend
depends_on:
- db_swe1
@@ -39,7 +39,7 @@ services:
expose:
- 80
container_name: ega_frontend_swe1
- image: nbis/ega:common
+ image: nbisweden/ega:common
volumes:
- ${CONF_swe1}:/etc/ega/conf.ini:ro
- ${CODE}:/root/ega
@@ -48,7 +48,7 @@ services:
# SFTP inbox for Sweden
inbox_swe1:
- build: images/inbox
+ #build: images/inbox
hostname: ega_inbox
depends_on:
- db_swe1
@@ -58,7 +58,7 @@ services:
ports:
- "2222:22"
container_name: ega_inbox_swe1
- image: nbis/ega:inbox
+ image: nbisweden/ega:inbox
volumes:
- ${CODE}:/root/ega
- inbox_swe1:/ega/inbox
@@ -68,7 +68,7 @@ services:
# SFTP inbox for Finland
inbox_fin1:
- build: images/inbox
+ #build: images/inbox
hostname: ega_inbox
depends_on:
- db_fin1
@@ -78,7 +78,7 @@ services:
ports:
- "2223:22"
container_name: ega_inbox_fin1
- image: nbis/ega:inbox
+ image: nbisweden/ega:inbox
volumes:
- ${CODE}:/root/ega
- inbox_fin1:/ega/inbox
@@ -88,14 +88,14 @@ services:
# Vault
vault_swe1:
- build: images/common
+ #build: images/common
depends_on:
- db_swe1
- mq_swe1
- inbox_swe1
hostname: ega_vault
container_name: ega_vault_swe1
- image: nbis/ega:common
+ image: nbisweden/ega:common
volumes:
- ${CODE}:/root/ega
- staging_swe1:/ega/staging
@@ -106,13 +106,13 @@ services:
# Ingestion Workers
ingest_swe1:
- build: images/worker
+ #build: images/worker
depends_on:
- db_swe1
- mq_swe1
- keys_swe1
- inbox_swe1
- image: nbis/ega:worker
+ image: nbisweden/ega:worker
environment:
- GPG_TTY=/dev/console
volumes:
@@ -129,12 +129,12 @@ services:
# Key server
keys_swe1:
env_file: .env.d/swe1/gpg
- build: images/worker
+ #build: images/worker
environment:
- GPG_TTY=/dev/console
hostname: ega_keys_swe1
container_name: ega_keys_swe1
- image: nbis/ega:worker
+ image: nbisweden/ega:worker
tty: true
volumes:
- ${CONF_swe1}:/etc/ega/conf.ini:ro
@@ -153,7 +153,7 @@ services:
# # Error Monitors
# monitors:
- # build: images/monitors
+ # #build: images/monitors
# # depends_on:
# # - db
# ports:
@@ -162,25 +162,26 @@ services:
# - 10514
# hostname: ega_monitors
# container_name: ega_monitors
- # image: nbis/ega:monitors
+ # image: nbisweden/ega:monitors
# command: ["rsyslogd", "-n"]
+ ############################################
# Faking Central EGA
-
+ ############################################
cega_mq:
- build: images/cega_mq
+ #build: images/cega_mq
hostname: cega_mq
ports:
- "15673:15672"
- image: nbis/ega:cega_mq
+ image: nbisweden/ega:cega_mq
container_name: cega_mq
volumes:
- ${CEGA_MQ_DEFS}:/etc/rabbitmq/defs.json:ro
cega_users:
env_file: .env.d/cega_instances
- build: images/cega_users
- image: nbis/ega:cega_users
+ #build: images/cega_users
+ image: nbisweden/ega:cega_users
container_name: cega_users
ports:
- "9100:80"
diff --git a/docker/images/Makefile b/docker/images/Makefile
index 0fdc87d8..c47dd023 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -1,12 +1,20 @@
EGA_IMAGES=common db mq inbox worker cega_users cega_mq monitors
+TARGET=nbisweden/ega
+
all: $(EGA_IMAGES)
-.PHONY: all $(EGA_IMAGES)
+.PHONY: all $(EGA_IMAGES) push
+
+all: $(EGA_IMAGES)
$(EGA_IMAGES):
- docker build --cache-from nbis/ega:$@ --tag nbis/ega:$@ $@
+ docker build --cache-from $(TARGET):$@ --tag $(TARGET):$@ $@
+
+push:
+ docker login
+ docker push $(TARGET)
clean:
docker images | awk '/none/{print $$3}' | while read n; do docker rmi $$n; done
From 6ab64ef44086b506fa92988abd78684b1d944158 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 13:36:58 +0100
Subject: [PATCH 058/528] No building of images, we pull them instead from
docker
---
.travis.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 3bc2b81e..df88bf0d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,7 +9,6 @@ before_install:
- |
cd docker
docker pull -a nbisweden/ega
- make -C images
docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega:worker /ega/boot.sh
bootstrap/populate.sh -f
sudo chown -R $USER .
From 8c8a04f4dc7d65cb51b38e78c5dd63ce1d33e39f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 14:50:58 +0100
Subject: [PATCH 059/528] Images with git tag, and on success, latest is pushed
to docker hub
---
.travis.yml | 12 ++++----
docker/ega.yml | 44 +++++++++++------------------
docker/images/Makefile | 12 ++++++--
docker/images/cega_users/Dockerfile | 2 +-
docker/images/worker/Dockerfile | 4 +--
5 files changed, 34 insertions(+), 40 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index df88bf0d..b5d8096f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,6 +9,7 @@ before_install:
- |
cd docker
docker pull -a nbisweden/ega
+ make -C images
docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega:worker /ega/boot.sh
bootstrap/populate.sh -f
sudo chown -R $USER .
@@ -20,12 +21,11 @@ script:
- cd ../tests
- mvn test -B
-# after_success:
-# - |
-# if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
-# docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
-# docker push nbisweden/ega
-# fi
+after_success:
+ - |
+ if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
+ make -C images push
+ fi
notifications:
email: false
diff --git a/docker/ega.yml b/docker/ega.yml
index de499399..0894b162 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -5,32 +5,28 @@ services:
# Local Message broker
mq_swe1:
#env_file: .env.d/swe1/mq
- #build: images/mq
hostname: ega_mq
ports:
- "15672:15672"
- image: nbisweden/ega:mq
+ image: nbisweden/ega-mq
container_name: ega_mq_swe1
# Postgres Database for Sweden
db_swe1:
env_file: .env.d/swe1/db
- #build: images/db
hostname: ega_db_swe1
container_name: ega_db_swe1
- image: nbisweden/ega:db
+ image: nbisweden/ega-db
# Postgres Database for Finland
db_fin1:
env_file: .env.d/fin1/db
- #build: images/db
hostname: ega_db_fin1
container_name: ega_db_fin1
- image: nbisweden/ega:db
+ image: nbisweden/ega-db
# ReST frontend
frontend_swe1:
- #build: images/common
hostname: ega_frontend
depends_on:
- db_swe1
@@ -39,7 +35,7 @@ services:
expose:
- 80
container_name: ega_frontend_swe1
- image: nbisweden/ega:common
+ image: nbisweden/ega-common
volumes:
- ${CONF_swe1}:/etc/ega/conf.ini:ro
- ${CODE}:/root/ega
@@ -48,7 +44,6 @@ services:
# SFTP inbox for Sweden
inbox_swe1:
- #build: images/inbox
hostname: ega_inbox
depends_on:
- db_swe1
@@ -58,7 +53,7 @@ services:
ports:
- "2222:22"
container_name: ega_inbox_swe1
- image: nbisweden/ega:inbox
+ image: nbisweden/ega-inbox
volumes:
- ${CODE}:/root/ega
- inbox_swe1:/ega/inbox
@@ -68,7 +63,6 @@ services:
# SFTP inbox for Finland
inbox_fin1:
- #build: images/inbox
hostname: ega_inbox
depends_on:
- db_fin1
@@ -78,7 +72,7 @@ services:
ports:
- "2223:22"
container_name: ega_inbox_fin1
- image: nbisweden/ega:inbox
+ image: nbisweden/ega-inbox
volumes:
- ${CODE}:/root/ega
- inbox_fin1:/ega/inbox
@@ -88,14 +82,13 @@ services:
# Vault
vault_swe1:
- #build: images/common
depends_on:
- db_swe1
- mq_swe1
- inbox_swe1
hostname: ega_vault
container_name: ega_vault_swe1
- image: nbisweden/ega:common
+ image: nbisweden/ega-common
volumes:
- ${CODE}:/root/ega
- staging_swe1:/ega/staging
@@ -106,13 +99,12 @@ services:
# Ingestion Workers
ingest_swe1:
- #build: images/worker
depends_on:
- db_swe1
- mq_swe1
- keys_swe1
- inbox_swe1
- image: nbisweden/ega:worker
+ image: nbisweden/ega-worker
environment:
- GPG_TTY=/dev/console
volumes:
@@ -129,12 +121,11 @@ services:
# Key server
keys_swe1:
env_file: .env.d/swe1/gpg
- #build: images/worker
environment:
- GPG_TTY=/dev/console
hostname: ega_keys_swe1
container_name: ega_keys_swe1
- image: nbisweden/ega:worker
+ image: nbisweden/ega-worker
tty: true
volumes:
- ${CONF_swe1}:/etc/ega/conf.ini:ro
@@ -152,36 +143,33 @@ services:
command: keys.sh
# # Error Monitors
- # monitors:
- # #build: images/monitors
+ # monitors_swe1:
# # depends_on:
- # # - db
+ # # - db_swe1
# ports:
# - "10514:10514"
# expose:
# - 10514
- # hostname: ega_monitors
- # container_name: ega_monitors
- # image: nbisweden/ega:monitors
+ # hostname: ega_monitors_swe1
+ # container_name: ega_monitors_swe1
+ # image: nbisweden/ega-monitors
# command: ["rsyslogd", "-n"]
############################################
# Faking Central EGA
############################################
cega_mq:
- #build: images/cega_mq
hostname: cega_mq
ports:
- "15673:15672"
- image: nbisweden/ega:cega_mq
+ image: nbisweden/ega-cega_mq
container_name: cega_mq
volumes:
- ${CEGA_MQ_DEFS}:/etc/rabbitmq/defs.json:ro
cega_users:
env_file: .env.d/cega_instances
- #build: images/cega_users
- image: nbisweden/ega:cega_users
+ image: nbisweden/ega-cega_users
container_name: cega_users
ports:
- "9100:80"
diff --git a/docker/images/Makefile b/docker/images/Makefile
index c47dd023..40070e8a 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -3,18 +3,24 @@ EGA_IMAGES=common db mq inbox worker cega_users cega_mq monitors
TARGET=nbisweden/ega
+TAG=$(shell git rev-parse --short HEAD)
+
all: $(EGA_IMAGES)
-.PHONY: all $(EGA_IMAGES) push
+.PHONY: all push $(EGA_IMAGES)
all: $(EGA_IMAGES)
+worker: common
+cega_users: common
+
$(EGA_IMAGES):
- docker build --cache-from $(TARGET):$@ --tag $(TARGET):$@ $@
+ docker build --tag $(TARGET)-$@:$(TAG) $@
+ docker tag $(TARGET)-$@:$(TAG) $(TARGET)-$@:latest
push:
docker login
- docker push $(TARGET)
+ for image in $(EGA_IMAGES); do docker push $(TARGET)-$image:latest; done
clean:
docker images | awk '/none/{print $$3}' | while read n; do docker rmi $$n; done
diff --git a/docker/images/cega_users/Dockerfile b/docker/images/cega_users/Dockerfile
index 55a33947..1373cd5c 100644
--- a/docker/images/cega_users/Dockerfile
+++ b/docker/images/cega_users/Dockerfile
@@ -1,4 +1,4 @@
-FROM nbis/ega:common
+FROM nbiswden/ega-common:latest
LABEL maintainer "Frédéric Haziza, NBIS"
##################################
diff --git a/docker/images/worker/Dockerfile b/docker/images/worker/Dockerfile
index f7062822..77d360a4 100644
--- a/docker/images/worker/Dockerfile
+++ b/docker/images/worker/Dockerfile
@@ -1,4 +1,4 @@
-FROM nbis/ega:common
+FROM nbisweden/ega-common:latest
LABEL maintainer "Frédéric Haziza, NBIS"
# Setup
@@ -17,7 +17,7 @@ ARG LIBKSBA_VERSION=1.3.5
ARG LIBNPTH_VERSION=1.5
ARG NCURSES_VERSION=6.0
ARG PINENTRY_VERSION=1.0.0
-ARG GNUPG_VERSION=2.2.1
+ARG GNUPG_VERSION=2.2.2
##############################################################
RUN mkdir -p /var/src/gnupg
From d6f897e4f3dce6957be3574891b410fbffd4cdb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 15:10:14 +0100
Subject: [PATCH 060/528] Using $CI_BUILD_REF
---
.travis.yml | 1 -
docker/images/Makefile | 7 ++++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index b5d8096f..51ab59fe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,6 @@ services:
before_install:
- |
cd docker
- docker pull -a nbisweden/ega
make -C images
docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega:worker /ega/boot.sh
bootstrap/populate.sh -f
diff --git a/docker/images/Makefile b/docker/images/Makefile
index 40070e8a..201c9e83 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -3,7 +3,9 @@ EGA_IMAGES=common db mq inbox worker cega_users cega_mq monitors
TARGET=nbisweden/ega
-TAG=$(shell git rev-parse --short HEAD)
+ifndef CI_BUILD_REF
+CI_BUILD_REF=$(shell git rev-parse --short HEAD)
+endif
all: $(EGA_IMAGES)
@@ -15,8 +17,7 @@ worker: common
cega_users: common
$(EGA_IMAGES):
- docker build --tag $(TARGET)-$@:$(TAG) $@
- docker tag $(TARGET)-$@:$(TAG) $(TARGET)-$@:latest
+ docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(CI_BUILD_REF) --tag $(TARGET)-$@:latest $@
push:
docker login
From 623238e948cbd9e147a7f8e782eb992b8828d4d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 15:22:12 +0100
Subject: [PATCH 061/528] Using $TRAVIS_COMMIT if exists
---
.travis.yml | 4 ++--
docker/images/Makefile | 6 ++++--
docker/images/cega_users/Dockerfile | 2 +-
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 51ab59fe..31471015 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,7 @@ services:
before_install:
- |
cd docker
- make -C images
+ make -C images -j 4
docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega:worker /ega/boot.sh
bootstrap/populate.sh -f
sudo chown -R $USER .
@@ -23,7 +23,7 @@ script:
after_success:
- |
if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
- make -C images push
+ make -C images push -j 4
fi
notifications:
diff --git a/docker/images/Makefile b/docker/images/Makefile
index 201c9e83..15b95f69 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -4,7 +4,9 @@ EGA_IMAGES=common db mq inbox worker cega_users cega_mq monitors
TARGET=nbisweden/ega
ifndef CI_BUILD_REF
-CI_BUILD_REF=$(shell git rev-parse --short HEAD)
+TAG=$(shell git rev-parse --short HEAD)
+else
+TAG=$(TRAVIS_COMMIT)
endif
all: $(EGA_IMAGES)
@@ -17,7 +19,7 @@ worker: common
cega_users: common
$(EGA_IMAGES):
- docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(CI_BUILD_REF) --tag $(TARGET)-$@:latest $@
+ docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(TAG) --tag $(TARGET)-$@:latest $@
push:
docker login
diff --git a/docker/images/cega_users/Dockerfile b/docker/images/cega_users/Dockerfile
index 1373cd5c..c17b8dfd 100644
--- a/docker/images/cega_users/Dockerfile
+++ b/docker/images/cega_users/Dockerfile
@@ -1,4 +1,4 @@
-FROM nbiswden/ega-common:latest
+FROM nbisweden/ega-common:latest
LABEL maintainer "Frédéric Haziza, NBIS"
##################################
From ed78aa29d87bd5631775f879a8053925fe810f63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 15:37:04 +0100
Subject: [PATCH 062/528] Moving rabbit password hash function to lib
---
docker/bootstrap/cega.sh | 12 ------------
docker/bootstrap/lib.sh | 15 ++++++++++++---
2 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/docker/bootstrap/cega.sh b/docker/bootstrap/cega.sh
index 36a0dba7..531941f2 100755
--- a/docker/bootstrap/cega.sh
+++ b/docker/bootstrap/cega.sh
@@ -127,18 +127,6 @@ popd > /dev/null
# Doing this instead:
echo -e "\t* a CEGA password for the MQ"
-function rabbitmq_hash {
- # 1) Generate a random 32 bit salt
- # 2) Concatenate that with the UTF-8 representation of the password
- # 3) Take the SHA-256 hash
- # 4) Concatenate the salt again
- # 5) Convert to base64 encoding
- local SALT=${2:-$(${OPENSSL} rand -hex 4)}
- (
- printf $SALT | xxd -p -r
- ( printf $SALT | xxd -p -r; printf $1 ) | ${OPENSSL} dgst -binary -sha256
- ) | base64
-}
function output_password_hashes {
declare -a tmp
diff --git a/docker/bootstrap/lib.sh b/docker/bootstrap/lib.sh
index 889eb515..69ca3ab6 100644
--- a/docker/bootstrap/lib.sh
+++ b/docker/bootstrap/lib.sh
@@ -27,9 +27,18 @@ function generate_password {
echo $p
}
-
-function print_arr {
- for x in "${!1[@]}"; do printf "[%s]=%s " "$x" "${array[$x]}" ; done
+function rabbitmq_hash {
+ # 1) Generate a random 32 bit salt
+ # 2) Concatenate that with the UTF-8 representation of the password
+ # 3) Take the SHA-256 hash
+ # 4) Concatenate the salt again
+ # 5) Convert to base64 encoding
+ local SALT=${2:-$(${OPENSSL:-openssl} rand -hex 4)}
+ (
+ printf $SALT | xxd -p -r
+ ( printf $SALT | xxd -p -r; printf $1 ) | ${OPENSSL:-openssl} dgst -binary -sha256
+ ) | base64
}
+
function join_by { local IFS="$1"; shift; echo -n "$*"; }
From 00ef610f1aacbefc54a6cc93c7c7d725f3388409 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 16:21:15 +0100
Subject: [PATCH 063/528] Fixing the .trace.cega-e
---
docker/bootstrap/boot.sh | 6 +++---
docker/bootstrap/populate.sh | 4 +++-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/docker/bootstrap/boot.sh b/docker/bootstrap/boot.sh
index 4906939e..3f7bd9f1 100755
--- a/docker/bootstrap/boot.sh
+++ b/docker/bootstrap/boot.sh
@@ -4,6 +4,6 @@ set -e
SCRIPT=$(dirname ${BASH_SOURCE[0]})
HERE=$PWD/${SCRIPT#./}
-$HERE/cega.sh -f
-$HERE/generate.sh -f -- swe1
-$HERE/generate.sh -f -- fin1
+$HERE/cega.sh -q -f
+$HERE/generate.sh -q -f -- swe1
+$HERE/generate.sh -q -f -- fin1
diff --git a/docker/bootstrap/populate.sh b/docker/bootstrap/populate.sh
index a0d12e3a..1c9dd56c 100755
--- a/docker/bootstrap/populate.sh
+++ b/docker/bootstrap/populate.sh
@@ -112,7 +112,9 @@ cp -rf $ABS_PRIVATE/.env.d $HERE/../.env.d
# Updating .trace with the right path
if [[ -f $ABS_PRIVATE/.trace.cega ]]; then
- sed -i -e "s;;$HERE;" $ABS_PRIVATE/.trace.cega
+ sed "s##$HERE#g" $ABS_PRIVATE/.trace.cega > $ABS_PRIVATE/.trace.cega.tmp
+ mv -f $ABS_PRIVATE/.trace.cega.tmp $ABS_PRIVATE/.trace.cega
+ # Note: The -i did not work. Dunno why.
fi
echomsg "docker-compose configuration files populated"
From 51f3a270c4e0dddbbab0af8ead6ced2fb4651ba7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 16:24:24 +0100
Subject: [PATCH 064/528] Correct worker image in Travis
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 31471015..29c58d78 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,7 +9,7 @@ before_install:
- |
cd docker
make -C images -j 4
- docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega:worker /ega/boot.sh
+ docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega-worker /ega/boot.sh
bootstrap/populate.sh -f
sudo chown -R $USER .
From 825f607e2101b40546c7c0e526f23072e2311d3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 16:56:06 +0100
Subject: [PATCH 065/528] Better printouts for bootstraps
---
.travis.yml | 2 +-
docker/bootstrap/boot.sh | 6 +++---
docker/bootstrap/cega.sh | 14 +++++++-------
docker/bootstrap/generate.sh | 18 +++++++++---------
docker/bootstrap/lib.sh | 27 +++++++++++++++++++++++++++
docker/bootstrap/populate.sh | 15 ++++-----------
6 files changed, 51 insertions(+), 31 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 29c58d78..d1b99835 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,7 +9,7 @@ before_install:
- |
cd docker
make -C images -j 4
- docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega-worker /ega/boot.sh
+ docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega-worker /ega/boot.sh -q -f
bootstrap/populate.sh -f
sudo chown -R $USER .
diff --git a/docker/bootstrap/boot.sh b/docker/bootstrap/boot.sh
index 3f7bd9f1..94729b2f 100755
--- a/docker/bootstrap/boot.sh
+++ b/docker/bootstrap/boot.sh
@@ -4,6 +4,6 @@ set -e
SCRIPT=$(dirname ${BASH_SOURCE[0]})
HERE=$PWD/${SCRIPT#./}
-$HERE/cega.sh -q -f
-$HERE/generate.sh -q -f -- swe1
-$HERE/generate.sh -q -f -- fin1
+$HERE/cega.sh $@
+$HERE/generate.sh $@ -- swe1
+$HERE/generate.sh $@ -- fin1
diff --git a/docker/bootstrap/cega.sh b/docker/bootstrap/cega.sh
index 531941f2..6d5e980e 100755
--- a/docker/bootstrap/cega.sh
+++ b/docker/bootstrap/cega.sh
@@ -47,7 +47,7 @@ else
exit 1
fi
-[[ $VERBOSE == 'no' ]] && exec 1>${HERE}/.log && FORCE='yes'
+#[[ $VERBOSE == 'no' ]] && exec 1>${HERE}/.log && FORCE='yes'
exec 2>${HERE}/.err
case $PRIVATE in
@@ -65,9 +65,9 @@ esac
rm_politely $ABS_PRIVATE/cega
mkdir -p $ABS_PRIVATE/cega/{users,mq}
-echo "Generating data for a fake Central EGA"
+echo -n "Generating data for a fake Central EGA"
-echo -e "\t* fake EGA users"
+echomsg "\t* fake EGA users"
EGA_USER_PASSWORD_JOHN=$(generate_password 16)
EGA_USER_PASSWORD_JANE=$(generate_password 16)
@@ -126,7 +126,7 @@ popd > /dev/null
# But then the queues and bindings are not properly set up
# Doing this instead:
-echo -e "\t* a CEGA password for the MQ"
+echomsg "\t* a CEGA password for the MQ"
function output_password_hashes {
declare -a tmp
@@ -200,7 +200,7 @@ EOF
rm_politely $ABS_PRIVATE/.env.d
mkdir -p $ABS_PRIVATE/.env.d
-echo "Generating the docker-compose configuration files"
+echomsg "Generating the docker-compose configuration files"
echo "LEGA_INSTANCES=${LEGA_INSTANCES}" > $ABS_PRIVATE/.env.d/cega_instances
for i in "${!CEGA_REST[@]}"; do
@@ -222,7 +222,7 @@ done
#########################################################################
-echo -e "\n=> Generation completed for CentralEGA \xF0\x9F\x91\x8D\n"
+task_complete "Generation completed for CentralEGA"
{
cat < $ABS_PRIVATE/.trace.cega
-[[ $VERBOSE == 'yes' ]] && cat $ABS_PRIVATE/.trace.cega
+#[[ $VERBOSE == 'yes' ]] && cat $ABS_PRIVATE/.trace.cega
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index 92e15a68..bd243869 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -47,7 +47,7 @@ else
exit 1
fi
-[[ $VERBOSE == 'no' ]] && exec 1>${HERE}/.log && FORCE='yes'
+#[[ $VERBOSE == 'no' ]] && exec 1>${HERE}/.log && FORCE='yes'
exec 2>${HERE}/.err
[[ -x $(readlink ${GPG}) ]] && echo "${GPG} is not executable" && exit 2
@@ -73,9 +73,9 @@ esac
rm_politely $ABS_PRIVATE/$INSTANCE
mkdir -p $ABS_PRIVATE/$INSTANCE/{gpg,rsa,certs}
-echo "Generating private data for ${INSTANCE^^}"
+echo -n "Generating private data for ${INSTANCE^^}"
-echo -e "\t* the GnuPG key"
+echomsg "\t* the GnuPG key"
cat > $ABS_PRIVATE/$INSTANCE/gen_key < $ABS_PRIVATE/$INSTANCE/keys.conf < $ABS_PRIVATE/.env.d/$INSTANCE/db < Generation completed for ${INSTANCE^^} \xF0\x9F\x91\x8D\n"
+task_complete "Generation completed for ${INSTANCE^^}"
cat > $ABS_PRIVATE/.trace.$INSTANCE < $1 \xF0\x9F\x91\x8D"
+ else
+ echo -e " \xF0\x9F\x91\x8D"
+ fi
+}
+
+
+function backup {
+ local target=$1
+ if [[ -e $target ]]; then
+ echomsg "Backing up $target"
+ mv -f $target $target.$(date +"%Y-%m-%d_%H:%M:%S")
+ fi
+}
+
function rm_politely {
local FOLDER=$1
diff --git a/docker/bootstrap/populate.sh b/docker/bootstrap/populate.sh
index 1c9dd56c..4eae217d 100755
--- a/docker/bootstrap/populate.sh
+++ b/docker/bootstrap/populate.sh
@@ -3,6 +3,8 @@
SCRIPT=$(dirname ${BASH_SOURCE[0]})
HERE=$PWD/${SCRIPT#./}
+source $HERE/lib.sh
+
# Defaults:
VERBOSE=yes
FORCE=no
@@ -38,9 +40,7 @@ while [[ $# -gt 0 ]]; do
shift
done
-function echomsg {
- [[ $VERBOSE == 'yes' ]] && echo $@
-}
+echo -n "Populating files"
case $PRIVATE in
/*) ABS_PRIVATE=$PRIVATE;;
@@ -66,13 +66,6 @@ esac
[[ -d $ABS_ENTRYPOINTS ]] || { echomsg "Entrypoints folder $ABS_ENTRYPOINTS not found. Exiting" 1>&2; exit 1; }
-function backup {
- local target=$1
- if [[ -e $target ]]; then
- echomsg "Backing up $target"
- mv -f $target $target.$(date +"%Y-%m-%d_%H:%M:%S")
- fi
-}
[[ $FORCE == 'yes' ]] || {
backup $HERE/../.env
@@ -117,4 +110,4 @@ if [[ -f $ABS_PRIVATE/.trace.cega ]]; then
# Note: The -i did not work. Dunno why.
fi
-echomsg "docker-compose configuration files populated"
+task_complete "docker-compose configuration files populated"
From eb840cd1f84186eba15d6392ea70d2cbd580f1e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 17:23:40 +0100
Subject: [PATCH 066/528] Routing key in CEGA_MQ
---
docker/bootstrap/generate.sh | 3 +++
docker/images/cega_mq/publish.py | 3 ++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index bd243869..642ad383 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -136,6 +136,9 @@ password = ${CEGA_MQ_PASSWORD}
vhost = ${INSTANCE}
heartbeat = 0
+file_queue = ${INSTANCE}.v1.commands.file
+file_routing = ${INSTANCE}.file.completed
+
[db]
host = ega_db_${INSTANCE}
username = ${DB_USER}
diff --git a/docker/images/cega_mq/publish.py b/docker/images/cega_mq/publish.py
index 53ea7ba5..f748f592 100644
--- a/docker/images/cega_mq/publish.py
+++ b/docker/images/cega_mq/publish.py
@@ -16,6 +16,7 @@
help="of the form 'amqp://:@:/'",
default='amqp://localhost:5672/%2F')
+parser.add_argument('routing', help='Routing key for the localega.v1 exchange')
parser.add_argument('user', help='Elixir ID')
parser.add_argument('filename', help='Filename in the user inbox')
@@ -37,7 +38,7 @@
parameters = pika.URLParameters(args.connection)
connection = pika.BlockingConnection(parameters)
channel = connection.channel()
-channel.basic_publish(exchange='localega.v1', routing_key='sweden.file',
+channel.basic_publish(exchange='localega.v1', routing_key='{}.file'.format(args.routing),
body=json.dumps(message),
properties=pika.BasicProperties(correlation_id=str(uuid.uuid4()), content_type='application/json',delivery_mode=2))
connection.close()
From d6728714562ae5ad7f2f2ee8216758c7eac30001 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 7 Nov 2017 19:05:57 +0100
Subject: [PATCH 067/528] Cleanup in the image Makefile
---
.travis.yml | 4 ++--
docker/bootstrap/cega.sh | 14 +++++++-------
docker/bootstrap/generate.sh | 14 ++++++++------
docker/bootstrap/populate.sh | 15 +++++++++------
docker/images/Makefile | 7 +++++--
5 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index d1b99835..e5ab0a2c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,8 +9,8 @@ before_install:
- |
cd docker
make -C images -j 4
- docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega-worker /ega/boot.sh -q -f
- bootstrap/populate.sh -f
+ docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega-worker /ega/boot.sh
+ bootstrap/populate.sh
sudo chown -R $USER .
install:
diff --git a/docker/bootstrap/cega.sh b/docker/bootstrap/cega.sh
index 6d5e980e..2da2bf10 100755
--- a/docker/bootstrap/cega.sh
+++ b/docker/bootstrap/cega.sh
@@ -7,8 +7,8 @@ HERE=$PWD/${SCRIPT#./}
source $HERE/lib.sh
# Defaults
-VERBOSE=yes
-FORCE=no
+VERBOSE=no
+FORCE=yes
PRIVATE=private
DEFAULTS=$HERE/defaults/cega
@@ -16,11 +16,11 @@ function usage {
echo "Usage: $0 [options] -- "
echo -e "\nOptions are:"
echo -e "\t--private_dir \tName of the main folder for private data"
- echo -e "\t--force, -f \tForce the re-creation of the subfolders"
echo ""
echo -e "\t--defaults \tDefaults data to be loaded [$DEFAULTS]"
echo ""
- echo -e "\t--quiet, -q \tRemoves the verbose output (and uses -f)"
+ echo -e "\t--verbose, -v \tShow verbose output"
+ echo -e "\t--polite, -p \tDo not force the re-creation of the subfolders. Ask instead"
echo -e "\t--help, -h \tOutputs this message and exits"
echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
echo ""
@@ -29,9 +29,9 @@ function usage {
# While there are arguments or '--' is reached
while [[ $# -gt 0 ]]; do
case "$1" in
- --quiet|-q) VERBOSE=no;;
--help|-h) usage; exit 0;;
- --force|-f) FORCE=yes;;
+ --verbose|-v) VERBOSE=yes;;
+ --polite|-p) FORCE=no;;
--private_dir) PRIVATE=$2; shift;;
--defaults) DEFAULTS=$2; shift;;
--) shift; break;;
@@ -47,7 +47,7 @@ else
exit 1
fi
-#[[ $VERBOSE == 'no' ]] && exec 1>${HERE}/.log && FORCE='yes'
+[[ $VERBOSE == 'yes' ]] && FORCE='no'
exec 2>${HERE}/.err
case $PRIVATE in
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index 642ad383..d56cbabd 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -7,17 +7,17 @@ HERE=$PWD/${SCRIPT#./}
source $HERE/lib.sh
# Defaults
-VERBOSE=yes
-FORCE=no
+VERBOSE=no
+FORCE=yes
PRIVATE=private
function usage {
echo "Usage: $0 [options] -- "
echo -e "\nOptions are:"
echo -e "\t--private_dir \tName of the main folder for private data"
- echo -e "\t--force, -f \tForce the re-creation of the subfolders"
echo ""
- echo -e "\t--quiet, -q \tRemoves the verbose output (and uses -f)"
+ echo -e "\t--verbose, -v \tShow verbose output"
+ echo -e "\t--polite, -p \tDo not force the re-creation of the subfolders. Ask instead"
echo -e "\t--help, -h \tOutputs this message and exits"
echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
echo ""
@@ -26,9 +26,9 @@ function usage {
# While there are arguments or '--' is reached
while [[ $# -gt 0 ]]; do
case "$1" in
- --quiet|-q) VERBOSE=no;;
--help|-h) usage; exit 0;;
- --force|-f) FORCE=yes;;
+ --verbose|-v) VERBOSE=yes;;
+ --polite|-p) FORCE=no;;
--private_dir) PRIVATE=$2; shift;;
--) shift; break;;
*) echo "$0: error - unrecognized option $1" 1>&2; usage; exit 1;;
@@ -36,6 +36,8 @@ while [[ $# -gt 0 ]]; do
shift
done
+[[ $VERBOSE == 'yes' ]] && FORCE='no'
+
# Loading the instance's settings
INSTANCE=$1
[[ -z ${INSTANCE} ]] && usage && exit 1
diff --git a/docker/bootstrap/populate.sh b/docker/bootstrap/populate.sh
index 4eae217d..5e754126 100755
--- a/docker/bootstrap/populate.sh
+++ b/docker/bootstrap/populate.sh
@@ -6,8 +6,8 @@ HERE=$PWD/${SCRIPT#./}
source $HERE/lib.sh
# Defaults:
-VERBOSE=yes
-FORCE=no
+VERBOSE=no
+FORCE=yes
PRIVATE=private
SOURCES=$HERE/../../src
ENTRYPOINTS=$HERE/../entrypoints
@@ -18,8 +18,9 @@ function usage {
echo -e "\t--private_dir \tPath location of private data folder"
echo -e "\t--sources \tPath Location of the src folder"
echo -e "\t--entrypoints \tPath Location of the entrypoints folder"
- echo -e "\t--force, -f \tDon't backup .env and .env.d if they exist"
- echo -e "\t--quiet, -q \tRemoves the verbose output (and uses -f)"
+ echo ""
+ echo -e "\t--verbose, -v \tShow verbose output"
+ echo -e "\t--polite, -p \tDo not force the re-creation of the subfolders. Ask instead"
echo -e "\t--help, -h \tOutputs this message and exits"
echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
echo ""
@@ -28,9 +29,9 @@ function usage {
# While there are arguments or '--' is reached
while [[ $# -gt 0 ]]; do
case "$1" in
- --quiet|-q) VERBOSE=no;;
--help|-h) usage; exit 0;;
- --force|-f) FORCE=yes;;
+ --verbose|-v) VERBOSE=yes;;
+ --polite|-p) FORCE=no;;
--sources) SOURCES=$2; shift;;
--entrypoints) ENTRYPOINTS=$2; shift;;
--private_dir) PRIVATE=$2; shift;;
@@ -40,6 +41,8 @@ while [[ $# -gt 0 ]]; do
shift
done
+[[ $VERBOSE == 'yes' ]] && FORCE='no'
+
echo -n "Populating files"
case $PRIVATE in
diff --git a/docker/images/Makefile b/docker/images/Makefile
index 15b95f69..1a119c3f 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -23,7 +23,10 @@ $(EGA_IMAGES):
push:
docker login
- for image in $(EGA_IMAGES); do docker push $(TARGET)-$image:latest; done
+ for image in $(EGA_IMAGES); do docker push $(TARGET)-$$image:latest; done
clean:
- docker images | awk '/none/{print $$3}' | while read n; do docker rmi $$n; done
+ @docker images -f "dangling=true" -q | uniq | while read n; do docker rmi $$n; done
+
+delete:
+ @docker images $(TARGET)-* --format "{{.ID}} {{.Tag}}" | awk '{ if ($$2 != "$(TAG)" && $$2 != "latest") print $$1; }' | uniq | while read n; do docker rmi $$n; done
From 0f6ccec72020f6be080581ecc1dc9a92f1094311 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 8 Nov 2017 00:03:59 +0100
Subject: [PATCH 068/528] Fixing -j4 for make in .travis.yml
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index e5ab0a2c..77bd1044 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,7 +23,7 @@ script:
after_success:
- |
if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
- make -C images push -j 4
+ make -C images -j 4 push
fi
notifications:
From 2b9c0d973e6c7964feca87ce1903bb6ca1ce54cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 8 Nov 2017 00:07:28 +0100
Subject: [PATCH 069/528] Images were updated, so is the doc
---
docker/README.md | 6 +++---
docker/bootstrap/README.md | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/docker/README.md b/docker/README.md
index 39bfd5c8..4970f78f 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -6,15 +6,15 @@ First [create the EGA docker images](images) beforehand, with `make -C images`.
You can then [generate the private data](bootstrap), with either:
- docker run --rm -it -v ${PWD}/bootstrap:/ega nbis/ega:worker /ega/boot.sh
+ docker run --rm -it -v ${PWD}/bootstrap:/ega nbisweden/ega-worker /ega/boot.sh
-> Note: you can run `bootstrap/{cega,generate}.sh` on your host machine but
+> Note: you can run `bootstrap/boot.sh` on your host machine but
> you need the required tools installed, including Python 3.6, GnuPG
> 2.2.1, OpenSSL, `readlink`, `xxd`, ...
You can afterwards copy the settings into place with
- bootstrap/populate.sh -f
+ bootstrap/populate.sh
The passwords are in `bootstrap/private/.trace.*` and the errors (if any) are in `bootstrap/.err`.
diff --git a/docker/bootstrap/README.md b/docker/bootstrap/README.md
index 8743f4ee..81ef2255 100644
--- a/docker/bootstrap/README.md
+++ b/docker/bootstrap/README.md
@@ -27,7 +27,7 @@ image that you have built up with the `make` command in the [images](../images)
In the same folder as `generate.sh`, run
- docker run --rm -it -v ${PWD}:/ega nbis/ega:worker /ega/generate.sh -f -- swe1
+ docker run --rm -it -v ${PWD}:/ega nbisweden/ega-worker /ega/generate.sh -- swe1
That will create a folder, named 'private', with all the settings
After that, you can run `./populate.sh` to move the `.env` and `.env.d/` into
From 53c8fe410cb552df580496c2f59b379d34954b1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 8 Nov 2017 00:30:49 +0100
Subject: [PATCH 070/528] Fixing doc and shebang
---
docker/README.md | 2 +-
docker/bootstrap/README.md | 2 +-
docker/bootstrap/defaults/fin1 | 3 +++
docker/bootstrap/defaults/swe1 | 3 +++
docker/bootstrap/populate.sh | 3 ++-
docker/images/README.md | 18 +++++++++---------
6 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/docker/README.md b/docker/README.md
index 4970f78f..661cfc41 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -10,7 +10,7 @@ You can then [generate the private data](bootstrap), with either:
> Note: you can run `bootstrap/boot.sh` on your host machine but
> you need the required tools installed, including Python 3.6, GnuPG
-> 2.2.1, OpenSSL, `readlink`, `xxd`, ...
+> 2.2.2, OpenSSL, `readlink`, `xxd`, ...
You can afterwards copy the settings into place with
diff --git a/docker/bootstrap/README.md b/docker/bootstrap/README.md
index 81ef2255..f895153d 100644
--- a/docker/bootstrap/README.md
+++ b/docker/bootstrap/README.md
@@ -22,7 +22,7 @@ destination location if there was already a version)
The passwords are in `private/.trace.*` (if you did not use `--private_dir`)
If you don't have the required tools installed on your machine (namely
-GnuPG 2.2.1, OpenSSL 1.0.2 and Python 3.6.1), you can use the `nbis/ega:worker`
+GnuPG 2.2.2, OpenSSL 1.0.2 and Python 3.6.1), you can use the `nbisweden/ega-worker:latest`
image that you have built up with the `make` command in the [images](../images) folder:
In the same folder as `generate.sh`, run
diff --git a/docker/bootstrap/defaults/fin1 b/docker/bootstrap/defaults/fin1
index 40ef28d0..8227162b 100644
--- a/docker/bootstrap/defaults/fin1
+++ b/docker/bootstrap/defaults/fin1
@@ -1,3 +1,6 @@
+#!/usr/bin/env bash
+set -e
+
GPG=gpg
OPENSSL=openssl
diff --git a/docker/bootstrap/defaults/swe1 b/docker/bootstrap/defaults/swe1
index 85a21800..33de67c8 100644
--- a/docker/bootstrap/defaults/swe1
+++ b/docker/bootstrap/defaults/swe1
@@ -1,3 +1,6 @@
+#!/usr/bin/env bash
+set -e
+
GPG=gpg
OPENSSL=openssl
diff --git a/docker/bootstrap/populate.sh b/docker/bootstrap/populate.sh
index 5e754126..ad8e1972 100755
--- a/docker/bootstrap/populate.sh
+++ b/docker/bootstrap/populate.sh
@@ -104,7 +104,8 @@ GPG_HOME_${INSTANCE}=$ABS_PRIVATE/${INSTANCE}/gpg
EOF
done
-cp -rf $ABS_PRIVATE/.env.d $HERE/../.env.d
+rm_politely $HERE/../.env.d
+cp -r $ABS_PRIVATE/.env.d $HERE/../.env.d
# Updating .trace with the right path
if [[ -f $ABS_PRIVATE/.trace.cega ]]; then
diff --git a/docker/images/README.md b/docker/images/README.md
index c97d8ea4..ca887d89 100644
--- a/docker/images/README.md
+++ b/docker/images/README.md
@@ -8,7 +8,7 @@ In the current folder, type `make` and the images are created in order.
It takes some time.
-Later on, if the `nbis/ega:common` does not need to be recreated, you
+Later on, if the `nbisweden/ega-common` does not need to be recreated, you
can type `make -j 4` (where `4` is an arbitrary number of parallel
builds: check the numbers of cores on your machine)
@@ -20,16 +20,16 @@ The following images are created locally:
| Repository | Tag | Role |
|------------|:--------:|------|
-| nbis/ega | db | Sets up a postgres database with appropriate tables |
-| nbis/ega | mq | Sets up a RabbitMQ message broker with appropriate accounts, exchanges, queues and bindings |
-| nbis/ega | common | Image including python 3.6.1 |
-| nbis/ega | inbox | SFTP server on top of `nbis/ega:common` |
-| nbis/ega | worker | Adding GnuPG 2.2.0 to `nbis/ega:common` |
-| nbis/ega | monitors | Including rsyslog |
+| nbisweden/ega-db | or latest | Sets up a postgres database with appropriate tables |
+| nbisweden/ega-mq | or latest | Sets up a RabbitMQ message broker with appropriate accounts, exchanges, queues and bindings |
+| nbisweden/ega-common | or latest | Image including python 3.6.1 |
+| nbisweden/ega-inbox | or latest | SFTP server on top of `nbisweden/ega-common:latest` |
+| nbisweden/ega-worker | or latest | Adding GnuPG 2.2.2 to `nbisweden/ega-common:latest` |
+| nbisweden/ega-monitors | or latest | Including rsyslog or logstash |
We also use 2 stubbing images in order to fake the necessary Central EGA components
| Repository | Tag | Role |
|------------|:--------:|------|
-| nbis/ega | cega\_users | Sets up a postgres database with appropriate tables |
-| nbis/ega | cega\_mq | Sets up a RabbitMQ message broker with appropriate accounts, exchanges, queues and bindings |
+| nbisweden/ega-cega\_users | or latest | Sets up a postgres database with appropriate tables |
+| nbisweden/ega-cega\_mq | or latest | Sets up a RabbitMQ message broker with appropriate accounts, exchanges, queues and bindings |
From 2d8dd1918ad2ebfc22809a6290b32f6d0f9003e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 8 Nov 2017 10:33:55 +0100
Subject: [PATCH 071/528] Fixing port issues
---
docker/bootstrap/generate.sh | 14 ++++++++++++++
docker/ega.yml | 7 +++++--
docker/entrypoints/ingest.sh | 8 +++-----
docker/entrypoints/keys.sh | 1 -
docker/entrypoints/vault.sh | 2 +-
src/lega/conf/defaults.ini | 2 +-
6 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index d56cbabd..8e568eff 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -130,6 +130,13 @@ log = debug
[ingestion]
gpg_cmd = /usr/local/bin/gpg --homedir ~/.gnupg --decrypt %(file)s
+# Keyserver communication
+keyserver_host = ega_keys_${INSTANCE}
+
+## Connecting to Local EGA
+[local.broker]
+host = ega_mq_${INSTANCE}
+
## Connecting to Central EGA
[cega.broker]
host = cega_mq
@@ -146,6 +153,13 @@ host = ega_db_${INSTANCE}
username = ${DB_USER}
password = ${DB_PASSWORD}
try = ${DB_TRY}
+
+[frontend]
+host = ega_frontend_${INSTANCE}
+
+[outgestion]
+# Keyserver communication
+keyserver_host = ega_keys_${INSTANCE}
EOF
diff --git a/docker/ega.yml b/docker/ega.yml
index 0894b162..d0b32fd2 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -95,7 +95,7 @@ services:
- vault_swe1:/ega/vault
- ${CONF_swe1}:/etc/ega/conf.ini:ro
- ${ENTRYPOINTS}/vault.sh:/usr/local/bin/vault.sh:ro
- command: vault.sh
+ command: ["vault.sh","swe1"]
# Ingestion Workers
ingest_swe1:
@@ -116,7 +116,7 @@ services:
- ${GPG_HOME_swe1}/pubring.kbx:/root/.gnupg/pubring.kbx:ro
- ${GPG_HOME_swe1}/trustdb.gpg:/root/.gnupg/trustdb.gpg
- ${ENTRYPOINTS}/ingest.sh:/usr/local/bin/ingest.sh:ro
- command: ingest.sh
+ command: ["ingest.sh","swe1"]
# Key server
keys_swe1:
@@ -127,6 +127,9 @@ services:
container_name: ega_keys_swe1
image: nbisweden/ega-worker
tty: true
+ ports:
+ - "9010"
+ - "9011"
volumes:
- ${CONF_swe1}:/etc/ega/conf.ini:ro
- ${KEYS_swe1}:/etc/ega/keys.ini:ro
diff --git a/docker/entrypoints/ingest.sh b/docker/entrypoints/ingest.sh
index f203b82e..6bf54ff8 100755
--- a/docker/entrypoints/ingest.sh
+++ b/docker/entrypoints/ingest.sh
@@ -6,16 +6,14 @@ cp -r /root/ega /root/run
pip3.6 install /root/run
# echo "Waiting for Keyserver"
-# until nc -4 --send-only ega_keys 9010 /dev/null; do sleep 1; done
-
+# until nc -4 --send-only ega_keys_$1 9010 /dev/null; do sleep 1; done
echo "Starting the socket forwarder"
-#ega-socket-forwarder /run/ega/S.gpg-agent ega_keys:9010 --certfile /etc/ega/ssl.cert &
-ega-socket-forwarder /root/.gnupg/S.gpg-agent ega_keys:9010 --certfile /etc/ega/ssl.cert &
+ega-socket-forwarder /root/.gnupg/S.gpg-agent ega_keys_$1:9010 --certfile /etc/ega/ssl.cert &
echo "Waiting for Central Message Broker"
until nc -4 --send-only cega_mq 5672 /dev/null; do sleep 1; done
echo "Waiting for Local Message Broker"
-until nc -4 --send-only ega_mq 5672 /dev/null; do sleep 1; done
+until nc -4 --send-only ega_mq_$1 5672 /dev/null; do sleep 1; done
echo "Starting the ingestion worker"
exec ega-ingest
diff --git a/docker/entrypoints/keys.sh b/docker/entrypoints/keys.sh
index c8e887af..2da3e431 100755
--- a/docker/entrypoints/keys.sh
+++ b/docker/entrypoints/keys.sh
@@ -37,5 +37,4 @@ KEYGRIP=$(/usr/local/bin/gpg -k --with-keygrip ega@nbis.se | awk '/Keygrip/{prin
unset GPG_PASSPHRASE
echo "Starting the gpg-agent proxy"
-#exec ega-socket-proxy '0.0.0.0:9010' /run/ega/S.gpg-agent.extra --certfile /etc/ega/ssl.cert --keyfile /etc/ega/ssl.key
exec ega-socket-proxy '0.0.0.0:9010' /root/.gnupg/S.gpg-agent.extra --certfile /etc/ega/ssl.cert --keyfile /etc/ega/ssl.key
diff --git a/docker/entrypoints/vault.sh b/docker/entrypoints/vault.sh
index a3d1b013..745d63ee 100755
--- a/docker/entrypoints/vault.sh
+++ b/docker/entrypoints/vault.sh
@@ -8,7 +8,7 @@ pip3.6 install /root/run
echo "Waiting for Central Message Broker"
until nc -4 --send-only cega_mq 5672 /dev/null; do sleep 1; done
echo "Waiting for Local Message Broker"
-until nc -4 --send-only ega_mq 5672 /dev/null; do sleep 1; done
+until nc -4 --send-only ega_mq_$1 5672 /dev/null; do sleep 1; done
echo "Starting the verifier"
ega-verify &
diff --git a/src/lega/conf/defaults.ini b/src/lega/conf/defaults.ini
index 8e7b43a4..a579ca1a 100644
--- a/src/lega/conf/defaults.ini
+++ b/src/lega/conf/defaults.ini
@@ -19,7 +19,7 @@ gpg_cmd = gpg --decrypt %(file)s
[outgestion]
# Keyserver communication
keyserver_host = ega_keys
-keyserver_port = 9010
+keyserver_port = 9011
keyserver_ssl_certfile = /etc/ega/ssl.cert
staging = /mnt/ega/staging
From 860170fc9f91d98c097f48d9f464800e5cd9c3d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 8 Nov 2017 12:27:20 +0100
Subject: [PATCH 072/528] Fixing the world
---
docker/bootstrap/generate.sh | 2 +-
docker/ega.yml | 2 +-
docker/entrypoints/ingest.sh | 2 +-
docker/entrypoints/keys.sh | 9 +++++----
4 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
index 8e568eff..f34ccc0e 100755
--- a/docker/bootstrap/generate.sh
+++ b/docker/bootstrap/generate.sh
@@ -146,7 +146,7 @@ vhost = ${INSTANCE}
heartbeat = 0
file_queue = ${INSTANCE}.v1.commands.file
-file_routing = ${INSTANCE}.file.completed
+file_routing = ${INSTANCE}.completed
[db]
host = ega_db_${INSTANCE}
diff --git a/docker/ega.yml b/docker/ega.yml
index d0b32fd2..4d8ac5af 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -127,7 +127,7 @@ services:
container_name: ega_keys_swe1
image: nbisweden/ega-worker
tty: true
- ports:
+ expose:
- "9010"
- "9011"
volumes:
diff --git a/docker/entrypoints/ingest.sh b/docker/entrypoints/ingest.sh
index 6bf54ff8..7ab74460 100755
--- a/docker/entrypoints/ingest.sh
+++ b/docker/entrypoints/ingest.sh
@@ -6,7 +6,7 @@ cp -r /root/ega /root/run
pip3.6 install /root/run
# echo "Waiting for Keyserver"
-# until nc -4 --send-only ega_keys_$1 9010 /dev/null; do sleep 1; done
+until nc -4 --send-only ega_keys_$1 9010 /dev/null; do sleep 1; done
echo "Starting the socket forwarder"
ega-socket-forwarder /root/.gnupg/S.gpg-agent ega_keys_$1:9010 --certfile /etc/ega/ssl.cert &
diff --git a/docker/entrypoints/keys.sh b/docker/entrypoints/keys.sh
index 2da3e431..b0794246 100755
--- a/docker/entrypoints/keys.sh
+++ b/docker/entrypoints/keys.sh
@@ -5,9 +5,6 @@ set -e
cp -r /root/ega /root/run
pip3.6 install /root/run
-echo "Starting the key management server"
-ega-keyserver --keys /etc/ega/keys.ini &
-
chmod 700 /root/.gnupg
pkill gpg-agent || true
#/usr/local/bin/gpgconf --kill gpg-agent || true
@@ -37,4 +34,8 @@ KEYGRIP=$(/usr/local/bin/gpg -k --with-keygrip ega@nbis.se | awk '/Keygrip/{prin
unset GPG_PASSPHRASE
echo "Starting the gpg-agent proxy"
-exec ega-socket-proxy '0.0.0.0:9010' /root/.gnupg/S.gpg-agent.extra --certfile /etc/ega/ssl.cert --keyfile /etc/ega/ssl.key
+#ega-socket-proxy '0.0.0.0:9010' /root/.gnupg/S.gpg-agent.extra --certfile /etc/ega/ssl.cert --keyfile /etc/ega/ssl.key &
+ega-socket-proxy '0.0.0.0:9010' /root/.gnupg/S.gpg-agent --certfile /etc/ega/ssl.cert --keyfile /etc/ega/ssl.key &
+
+echo "Starting the key management server"
+exec ega-keyserver --keys /etc/ega/keys.ini
From 73fbdb04bc1924ceb0c838a0b82a39ad1ef279df Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Wed, 8 Nov 2017 14:32:55 +0100
Subject: [PATCH 073/528] Actualize test-suite.
---
.../test/java/se/nbis/lega/cucumber/Utils.java | 4 ++--
.../se/nbis/lega/cucumber/steps/Ingestion.java | 17 +++++++++--------
.../se/nbis/lega/cucumber/steps/Uploading.java | 4 ++--
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index ad1d832f..baafab90 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -61,8 +61,8 @@ public String executeWithinContainer(Container container, String... command) thr
* @return Property value.
* @throws IOException In case it's not possible to read trace file.
*/
- public String readTraceProperty(String property) throws IOException {
- File trace = new File(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/.trace");
+ public String readTraceProperty(String fileName, String property) throws IOException {
+ File trace = new File(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/" + fileName);
return FileUtils.readLines(trace, Charset.defaultCharset()).
stream().
filter(l -> l.startsWith(property)).
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
index a2f6d831..5659809c 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -18,8 +18,8 @@ public Ingestion(Context context) {
Given("^I have CEGA username and password$", () -> {
try {
- context.setCegaMQUser(utils.readTraceProperty("CEGA_MQ_USER"));
- context.setCegaMQPassword(utils.readTraceProperty("CEGA_MQ_PASSWORD"));
+ context.setCegaMQUser("cega_swe1");
+ context.setCegaMQPassword(utils.readTraceProperty(".trace.cega", "CEGA_MQ_swe1_PASSWORD"));
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -29,11 +29,12 @@ public Ingestion(Context context) {
When("^I ingest file from the LocalEGA inbox$", () -> {
try {
File encryptedFile = context.getEncryptedFile();
- utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "/cega_mq"),
- String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
+ utils.executeWithinContainer(utils.findContainer("nbisweden/ega-cega_mq", "/cega_mq"),
+ String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s %s --unenc %s --enc %s",
context.getCegaMQUser(),
context.getCegaMQPassword(),
- utils.readTraceProperty("CEGA_MQ_VHOST"),
+ "swe1",
+ "swe1",
context.getUser(),
encryptedFile.getName(),
utils.calculateMD5(context.getRawFile()),
@@ -48,10 +49,10 @@ public Ingestion(Context context) {
try {
Thread.sleep(1000);
String query = String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName());
- String output = utils.executeWithinContainer(utils.findContainer("nbis/ega:db", "/ega_db"),
- "psql", "-U", utils.readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
+ String output = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-db", "/ega_db_swe1"),
+ "psql", "-U", utils.readTraceProperty(".trace.swe1", "DB_USER"), "-d", "lega", "-c", query);
String vaultFileName = output.split(System.getProperty("line.separator"))[2];
- String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "/ega_vault"), "cat", vaultFileName.trim());
+ String cat = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-common", "/ega_vault_swe1"), "cat", vaultFileName.trim());
Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index 586cfcbf..fcdde375 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -30,11 +30,11 @@ public Uploading(Context context) {
Volume dataVolume = new Volume("/data");
Volume gpgVolume = new Volume("/root/.gnupg");
CreateContainerResponse createContainerResponse = dockerClient.
- createContainerCmd("nbis/ega:worker").
+ createContainerCmd("nbisweden/ega-worker").
withVolumes(dataVolume, gpgVolume).
withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
- withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
+ withCmd(utils.readTraceProperty(".trace.swe1", "GPG exec"), "-r", utils.readTraceProperty(".trace.swe1", "GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
exec();
dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
From 7d7e664cf542065b3d6523d50cd721e7806e5adc Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Wed, 8 Nov 2017 14:47:58 +0100
Subject: [PATCH 074/528] Fix path to GPG in a test-suite.
---
tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index fcdde375..cd10200a 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -33,7 +33,7 @@ public Uploading(Context context) {
createContainerCmd("nbisweden/ega-worker").
withVolumes(dataVolume, gpgVolume).
withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
- new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
+ new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/swe1/gpg", gpgVolume, AccessMode.ro)).
withCmd(utils.readTraceProperty(".trace.swe1", "GPG exec"), "-r", utils.readTraceProperty(".trace.swe1", "GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
exec();
dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
From 37afc1298b882972c8116c0b6e7e6340091ae26b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 8 Nov 2017 15:19:08 +0100
Subject: [PATCH 075/528] Fixing the docker image caching
---
.travis.yml | 3 ++-
docker/images/Makefile | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 77bd1044..8686a810 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -22,7 +22,8 @@ script:
after_success:
- |
- if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
+ if [ "$TRAVIS_BRANCH" == "dev" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
+ docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
make -C images -j 4 push
fi
diff --git a/docker/images/Makefile b/docker/images/Makefile
index 1a119c3f..01440b47 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -19,14 +19,14 @@ worker: common
cega_users: common
$(EGA_IMAGES):
+ -docker pull $(TARGET)-$@:latest
docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(TAG) --tag $(TARGET)-$@:latest $@
push:
- docker login
for image in $(EGA_IMAGES); do docker push $(TARGET)-$$image:latest; done
clean:
@docker images -f "dangling=true" -q | uniq | while read n; do docker rmi $$n; done
delete:
- @docker images $(TARGET)-* --format "{{.ID}} {{.Tag}}" | awk '{ if ($$2 != "$(TAG)" && $$2 != "latest") print $$1; }' | uniq | while read n; do docker rmi $$n; done
+ @docker images $(TARGET)-* --format "{{.Repository}} {{.Tag}}" | awk '{ if ($$2 != "$(TAG)" && $$2 != "latest") print $$1":"$$2; }' | uniq | while read n; do docker rmi $$n; done
From 46943d32643d4c0163be5ed617f57692795630bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 9 Nov 2017 01:07:49 +0100
Subject: [PATCH 076/528] Codacy fix
---
docker/bootstrap/lib.sh | 2 ++
docker/entrypoints/keys.sh | 1 -
docker/images/db/db.sql | 3 ---
3 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/docker/bootstrap/lib.sh b/docker/bootstrap/lib.sh
index b1ca249c..a7269d15 100644
--- a/docker/bootstrap/lib.sh
+++ b/docker/bootstrap/lib.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+
function echomsg {
[[ -z "$VERBOSE" ]] && echo $@ && return 0
if [[ "$VERBOSE" == 'yes' ]]; then
diff --git a/docker/entrypoints/keys.sh b/docker/entrypoints/keys.sh
index b0794246..1229ac60 100755
--- a/docker/entrypoints/keys.sh
+++ b/docker/entrypoints/keys.sh
@@ -34,7 +34,6 @@ KEYGRIP=$(/usr/local/bin/gpg -k --with-keygrip ega@nbis.se | awk '/Keygrip/{prin
unset GPG_PASSPHRASE
echo "Starting the gpg-agent proxy"
-#ega-socket-proxy '0.0.0.0:9010' /root/.gnupg/S.gpg-agent.extra --certfile /etc/ega/ssl.cert --keyfile /etc/ega/ssl.key &
ega-socket-proxy '0.0.0.0:9010' /root/.gnupg/S.gpg-agent --certfile /etc/ega/ssl.cert --keyfile /etc/ega/ssl.key &
echo "Starting the key management server"
diff --git a/docker/images/db/db.sql b/docker/images/db/db.sql
index 8a2e88fc..a95625f6 100644
--- a/docker/images/db/db.sql
+++ b/docker/images/db/db.sql
@@ -1,6 +1,3 @@
--- DROP DATABASE IF EXISTS lega;
--- CREATE DATABASE lega;
-
\connect lega
SET TIME ZONE 'Europe/Stockholm';
From 14fb9d63f0803ad7a596940aba3e024aa9e4f59d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 9 Nov 2017 01:10:30 +0100
Subject: [PATCH 077/528] small readme update
---
docker/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/README.md b/docker/README.md
index 661cfc41..48981cd2 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -24,7 +24,7 @@ Alternatively, you can setup all [configuration files by hand](bootstrap/yoursel
docker-compose up -d
-Use `docker-compose up -d --scale ingest=3` instead, if you want to
+Use `docker-compose up -d --scale ingest_swe1=3` instead, if you want to
start 3 ingestion workers.
Note that, in this architecture, we use 3 separate volumes: one for
From e7761c31fc736e0e0e92db97a8c8727f6833e27a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 9 Nov 2017 11:51:00 +0100
Subject: [PATCH 078/528] Removing pushd/popd
---
docker/bootstrap/cega.sh | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/docker/bootstrap/cega.sh b/docker/bootstrap/cega.sh
index 2da2bf10..4766856c 100755
--- a/docker/bootstrap/cega.sh
+++ b/docker/bootstrap/cega.sh
@@ -107,15 +107,17 @@ EOF
mkdir -p $ABS_PRIVATE/cega/users/{swe1,fin1}
# They all have access to SWE1
-pushd $ABS_PRIVATE/cega/users/swe1 > /dev/null
-ln -s ../john.yml .
-ln -s ../jane.yml .
-ln -s ../taylor.yml .
-popd > /dev/null
+( # In a subshell
+ cd $ABS_PRIVATE/cega/users/swe1
+ ln -s ../john.yml .
+ ln -s ../jane.yml .
+ ln -s ../taylor.yml .
+)
# John has also access to FIN1
-pushd $ABS_PRIVATE/cega/users/fin1 > /dev/null
-ln -s ../john.yml .
-popd > /dev/null
+(
+ cd $ABS_PRIVATE/cega/users/fin1
+ ln -s ../john.yml .
+)
#########################################################################
From f21ff0e8b61109feb398c5ace896ca67eef8367f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 9 Nov 2017 15:19:48 +0100
Subject: [PATCH 079/528] Changing the folder for docker push
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 8686a810..83b774f1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,7 +24,7 @@ after_success:
- |
if [ "$TRAVIS_BRANCH" == "dev" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
- make -C images -j 4 push
+ make -C docker/images -j 4 push
fi
notifications:
From 45a4ca32e0fc37463cdf04f40d49020afcd5bae9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 9 Nov 2017 17:45:47 +0100
Subject: [PATCH 080/528] Finding the right makefile
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 83b774f1..9df1eb2c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,7 +24,7 @@ after_success:
- |
if [ "$TRAVIS_BRANCH" == "dev" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
- make -C docker/images -j 4 push
+ make -C ../docker/images -j 4 push
fi
notifications:
From ef396377e95079614a72d7848309c394f109853e Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 14:30:23 +0100
Subject: [PATCH 081/528] Refactor tests, add authentication tests.
---
.../java/se/nbis/lega/cucumber/Context.java | 10 +-
.../java/se/nbis/lega/cucumber/Tests.java | 8 --
.../java/se/nbis/lega/cucumber/Utils.java | 44 ++++++++-
.../lega/cucumber/hooks/BeforeAfterHooks.java | 42 ++++++++
.../lega/cucumber/steps/Authentication.java | 99 ++++++++++++++++---
.../nbis/lega/cucumber/steps/Ingestion.java | 19 ++--
.../nbis/lega/cucumber/steps/Uploading.java | 27 +++--
.../cucumber/features/authentication.feature | 34 ++++++-
.../cucumber/features/ingestion.feature | 5 +-
.../cucumber/features/uploading.feature | 5 +-
10 files changed, 235 insertions(+), 58 deletions(-)
create mode 100644 tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Context.java b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
index afcdb288..d7819dfd 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Context.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
@@ -2,11 +2,8 @@
import lombok.Data;
import net.schmizz.sshj.sftp.SFTPClient;
-import org.apache.commons.io.FileUtils;
import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
@Data
public class Context {
@@ -22,11 +19,6 @@ public class Context {
private File rawFile;
private File encryptedFile;
- public Context() throws IOException {
- dataFolder = new File("data");
- dataFolder.mkdir();
- rawFile = File.createTempFile("data", ".raw", dataFolder);
- FileUtils.writeStringToFile(rawFile, "hello", Charset.defaultCharset());
- }
+ private boolean authenticationFailed;
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Tests.java b/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
index 1c18e386..e442eb01 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
@@ -15,12 +15,4 @@
features = "src/test/resources/cucumber/features"
)
public class Tests {
-
- public static final String DATA_FOLDER_PATH = "data";
-
- @AfterClass
- public static void teardown() throws IOException {
- FileUtils.deleteDirectory(new File(DATA_FOLDER_PATH));
- }
-
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index baafab90..0a0e9e65 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -1,10 +1,15 @@
package se.nbis.lega.cucumber;
import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.model.AccessMode;
+import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Container;
+import com.github.dockerjava.api.model.Volume;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.command.ExecStartResultCallback;
+import com.github.dockerjava.core.command.WaitContainerResultCallback;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ArrayUtils;
@@ -54,6 +59,43 @@ public String executeWithinContainer(Container container, String... command) thr
return new String(outputStream.toByteArray());
}
+ /**
+ * Executes PSQL query.
+ *
+ * @param query Query to execute.
+ * @return Query output.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public String executeDBQuery(String query) throws IOException, InterruptedException {
+ return executeWithinContainer(findContainer("nbis/ega:db", "ega_db"), "psql", "-U", readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
+ }
+
+ /**
+ * Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
+ *
+ * @param from Folder to mount from.
+ * @param to Folder to mount to.
+ * @param command Command to execute.
+ * @throws InterruptedException In case the command execution is interrupted.
+ */
+ public void spawnWorkerAndExecute(String from, String to, String... command) throws InterruptedException {
+ Volume dataVolume = new Volume(to);
+ Volume gpgVolume = new Volume("/root/.gnupg");
+ CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerCmd("nbis/ega:worker").
+ withVolumes(dataVolume, gpgVolume).
+ withBinds(new Bind(from, dataVolume),
+ new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
+ withCmd(command).
+ exec();
+ dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
+ WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
+ dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback);
+ resultCallback.awaitCompletion();
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).exec();
+ }
+
/**
* Reads property from the trace file.
*
@@ -81,7 +123,7 @@ public Container findContainer(String imageName, String containerName) {
return dockerClient.listContainersCmd().exec().
stream().
filter(c -> c.getImage().equals(imageName)).
- filter(c -> ArrayUtils.contains(c.getNames(), containerName)).
+ filter(c -> ArrayUtils.contains(c.getNames(), "/" + containerName)).
findAny().
orElse(null);
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
new file mode 100644
index 00000000..30c3fb9d
--- /dev/null
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -0,0 +1,42 @@
+package se.nbis.lega.cucumber.hooks;
+
+import cucumber.api.java.After;
+import cucumber.api.java.Before;
+import cucumber.api.java8.En;
+import org.apache.commons.io.FileUtils;
+import se.nbis.lega.cucumber.Context;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+public class BeforeAfterHooks implements En {
+
+ private Context context;
+
+ public BeforeAfterHooks(Context context) {
+ this.context = context;
+ }
+
+ @Before
+ public void setUp() throws IOException {
+ File dataFolder = new File("data");
+ dataFolder.mkdir();
+ File rawFile = File.createTempFile("data", ".raw", dataFolder);
+ FileUtils.writeStringToFile(rawFile, "hello", Charset.defaultCharset());
+ context.setDataFolder(dataFolder);
+ context.setRawFile(rawFile);
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ FileUtils.deleteDirectory(context.getDataFolder());
+ String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
+ File cegaUsersFolder = new File(cegaUsersFolderPath);
+ Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
+ }
+
+}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 3549c673..e9e01aa0 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -1,46 +1,121 @@
package se.nbis.lega.cucumber.steps;
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.model.Bind;
+import com.github.dockerjava.api.model.Container;
+import com.github.dockerjava.api.model.Volume;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
+import net.schmizz.sshj.userauth.UserAuthException;
+import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.UUID;
@Slf4j
public class Authentication implements En {
public Authentication(Context context) {
- Given("^I am a user \"([^\"]*)\"$", context::setUser);
+ Utils utils = context.getUtils();
- Given("^I have a private key$",
+ Given("^I am a user$", () -> context.setUser(UUID.randomUUID().toString()));
+
+ Given("^I have an account at Central EGA$", () -> {
+ DockerClient dockerClient = utils.getDockerClient();
+ String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
+ String name = UUID.randomUUID().toString();
+ String dataFolderName = context.getDataFolder().getName();
+ CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerCmd("nbis/ega:worker").
+ withName(name).
+ withCmd("sleep", "1000").
+ withBinds(new Bind(cegaUsersFolderPath, new Volume("/" + dataFolderName))).
+ exec();
+ dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
+ try {
+ Container tempWorker = utils.findContainer("nbis/ega:worker", name);
+ double password = Math.random();
+ String user = context.getUser();
+ utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
+ String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
+ File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
+ FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ } finally {
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
+ }
+ });
+
+ Given("^I have correct private key$",
() -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", context.getUser()))));
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ Given("^I have incorrect private key$",
+ () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
+
+ When("^my account expires$", () -> {
+ authenticate(context);
+ try {
+ Thread.sleep(1000);
+ utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
+
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> authenticate(context));
+
+ Then("^I am in the local database$", () -> {
try {
- SSHClient ssh = new SSHClient();
- ssh.addHostKeyVerifier(new PromiscuousVerifier());
- ssh.connect("localhost", 2222);
- ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
- context.setSftp(ssh.newSFTPClient());
- } catch (IOException e) {
+ String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
+ String count = output.split(System.getProperty("line.separator"))[2];
+ Assert.assertEquals(1, Integer.parseInt(count.trim()));
+ } catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
}
});
- Then("^I'm logged in successfully$", () -> {
+ Then("^I am not in the local database$", () -> {
try {
- Assert.assertEquals("inbox", context.getSftp().ls("/").iterator().next().getName());
- } catch (IOException e) {
+ String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
+ String count = output.split(System.getProperty("line.separator"))[2];
+ Assert.assertEquals(0, Integer.parseInt(count.trim()));
+ } catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
}
});
+
+ Then("^I'm logged in successfully$", () -> Assert.assertFalse(context.isAuthenticationFailed()));
+
+ Then("^authentication fails$", () -> Assert.assertTrue(context.isAuthenticationFailed()));
+
+ }
+
+ private void authenticate(Context context) {
+ try {
+ SSHClient ssh = new SSHClient();
+ ssh.addHostKeyVerifier(new PromiscuousVerifier());
+ ssh.connect("localhost", 2222);
+ ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
+ context.setSftp(ssh.newSFTPClient());
+ } catch (UserAuthException e) {
+ log.error(e.getMessage(), e);
+ context.setAuthenticationFailed(true);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
}
}
\ No newline at end of file
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
index 5659809c..3560a8d7 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -18,8 +18,8 @@ public Ingestion(Context context) {
Given("^I have CEGA username and password$", () -> {
try {
- context.setCegaMQUser("cega_swe1");
- context.setCegaMQPassword(utils.readTraceProperty(".trace.cega", "CEGA_MQ_swe1_PASSWORD"));
+ context.setCegaMQUser(utils.readTraceProperty("CEGA_MQ_USER"));
+ context.setCegaMQPassword(utils.readTraceProperty("CEGA_MQ_PASSWORD"));
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -29,16 +29,16 @@ public Ingestion(Context context) {
When("^I ingest file from the LocalEGA inbox$", () -> {
try {
File encryptedFile = context.getEncryptedFile();
- utils.executeWithinContainer(utils.findContainer("nbisweden/ega-cega_mq", "/cega_mq"),
- String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s %s --unenc %s --enc %s",
+ utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "cega_mq"),
+ String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
context.getCegaMQUser(),
context.getCegaMQPassword(),
- "swe1",
- "swe1",
+ utils.readTraceProperty("CEGA_MQ_VHOST"),
context.getUser(),
encryptedFile.getName(),
utils.calculateMD5(context.getRawFile()),
utils.calculateMD5(encryptedFile)).split(" "));
+ Thread.sleep(1000);
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -47,12 +47,9 @@ public Ingestion(Context context) {
Then("^the file is ingested successfully$", () -> {
try {
- Thread.sleep(1000);
- String query = String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName());
- String output = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-db", "/ega_db_swe1"),
- "psql", "-U", utils.readTraceProperty(".trace.swe1", "DB_USER"), "-d", "lega", "-c", query);
+ String output = utils.executeDBQuery(String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName()));
String vaultFileName = output.split(System.getProperty("line.separator"))[2];
- String cat = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-common", "/ega_vault_swe1"), "cat", vaultFileName.trim());
+ String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "ega_vault"), "cat", vaultFileName.trim());
Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index cd10200a..dcae27d6 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -26,24 +26,32 @@ public Uploading(Context context) {
Given("^I have an encrypted file$", () -> {
DockerClient dockerClient = utils.getDockerClient();
File rawFile = context.getRawFile();
+ String dataFolderName = context.getDataFolder().getName();
+ Volume dataVolume = new Volume("/" + dataFolderName);
+ Volume gpgVolume = new Volume("/root/.gnupg");
+ CreateContainerResponse createContainerResponse = null;
try {
- Volume dataVolume = new Volume("/data");
- Volume gpgVolume = new Volume("/root/.gnupg");
- CreateContainerResponse createContainerResponse = dockerClient.
- createContainerCmd("nbisweden/ega-worker").
+ createContainerResponse = dockerClient.
+ createContainerCmd("nbis/ega:worker").
withVolumes(dataVolume, gpgVolume).
- withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
- new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/swe1/gpg", gpgVolume, AccessMode.ro)).
- withCmd(utils.readTraceProperty(".trace.swe1", "GPG exec"), "-r", utils.readTraceProperty(".trace.swe1", "GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
+ withBinds(new Bind(Paths.get(dataFolderName).toAbsolutePath().toString(), dataVolume),
+ new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
+ withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", String.format("/%s/%s.enc", dataFolderName, rawFile.getName()), String.format("/%s/%s", dataFolderName, rawFile.getName())).
exec();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ try {
dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback);
resultCallback.awaitCompletion();
- dockerClient.removeContainerCmd(createContainerResponse.getId()).exec();
- } catch (IOException | InterruptedException e) {
+ } catch (InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
+ } finally {
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
}
context.setEncryptedFile(new File(rawFile.getAbsolutePath() + ".enc"));
});
@@ -54,7 +62,6 @@ public Uploading(Context context) {
context.getSftp().put(encryptedFile.getAbsolutePath(), encryptedFile.getName());
} catch (IOException e) {
log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
}
});
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index 4828a3fb..166d0211 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -1,8 +1,36 @@
Feature: Authentication
As a user I want to be able to authenticate against LocalEGA inbox
- Scenario: Authenticate against LocalEGA inbox using private key
- Given I am a user "john"
- And I have a private key
+ Scenario: User population in LocalEGA DB from Central EGA
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then I am in the local database
+
+ Scenario: User doesn't exist in Central EGA, but tries to authenticate against LocalEGA inbox
+ Given I am a user
+ And I have correct private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
+ Scenario: User exists in Central EGA, but uses incorrect private key for authentication
+ Given I am a user
+ And I have an account at Central EGA
+ And I have incorrect private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
+ Scenario: User exists in Central EGA, but his account has expired
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
+ When my account expires
+ Then I am not in the local database
+
+ Scenario: User exists in Central EGA and uses correct private key for authentication
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then I'm logged in successfully
\ No newline at end of file
diff --git a/tests/src/test/resources/cucumber/features/ingestion.feature b/tests/src/test/resources/cucumber/features/ingestion.feature
index d93b426e..52804f16 100644
--- a/tests/src/test/resources/cucumber/features/ingestion.feature
+++ b/tests/src/test/resources/cucumber/features/ingestion.feature
@@ -2,8 +2,9 @@ Feature: Ingestion
As a user I want to be able to ingest files from the LocalEGA inbox
Scenario: Ingest files from the LocalEGA inbox
- Given I am a user "john"
- And I have a private key
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
And I upload encrypted file to the LocalEGA inbox via SFTP
diff --git a/tests/src/test/resources/cucumber/features/uploading.feature b/tests/src/test/resources/cucumber/features/uploading.feature
index 12abdbf5..9adf5c3c 100644
--- a/tests/src/test/resources/cucumber/features/uploading.feature
+++ b/tests/src/test/resources/cucumber/features/uploading.feature
@@ -2,8 +2,9 @@ Feature: Uploading
As a user I want to be able to upload files to the LocalEGA inbox
Scenario: Upload files to the LocalEGA inbox
- Given I am a user "john"
- And I have a private key
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
When I upload encrypted file to the LocalEGA inbox via SFTP
From 320bc710a4f121a9a011ea0017d95614fe00d6de Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 16:52:48 +0100
Subject: [PATCH 082/528] Fix SFTP library bug (work-around). Use temp users in
testing.
---
.../lega/cucumber/hooks/BeforeAfterHooks.java | 3 ++-
.../nbis/lega/cucumber/steps/Authentication.java | 16 ++++++++++++----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index 30c3fb9d..bbf24f9f 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -32,11 +32,12 @@ public void setUp() throws IOException {
}
@After
- public void tearDown() throws IOException {
+ public void tearDown() throws IOException, InterruptedException {
FileUtils.deleteDirectory(context.getDataFolder());
String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
File cegaUsersFolder = new File(cegaUsersFolderPath);
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
+ context.getUtils().executeDBQuery(String.format("delete from users where elixir_id = '%s'", context.getUser()));
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index e9e01aa0..43d3c80c 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -47,6 +47,7 @@ public Authentication(Context context) {
String user = context.getUser();
utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("chmod 400 /%s/%s.sec", dataFolderName, user).split(" "));
String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
@@ -73,7 +74,9 @@ public Authentication(Context context) {
}
});
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> authenticate(context));
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ authenticate(context);
+ });
Then("^I am in the local database$", () -> {
try {
@@ -104,17 +107,22 @@ public Authentication(Context context) {
}
private void authenticate(Context context) {
+ // need to retry twice due to bug in SSHJ library
+ retryAuthenticationAttempt(context);
+ retryAuthenticationAttempt(context);
+ }
+
+ private void retryAuthenticationAttempt(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
context.setSftp(ssh.newSFTPClient());
- } catch (UserAuthException e) {
+ context.setAuthenticationFailed(false);
+ } catch (Exception e) {
log.error(e.getMessage(), e);
context.setAuthenticationFailed(true);
- } catch (IOException e) {
- log.error(e.getMessage(), e);
}
}
From eb79252f9aee6afa554cd496b6f53725e3b34049 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 17:17:35 +0100
Subject: [PATCH 083/528] Reuse single test user across all scenarios.
---
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 43d3c80c..1dfba558 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -9,7 +9,6 @@
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
-import net.schmizz.sshj.userauth.UserAuthException;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import se.nbis.lega.cucumber.Context;
@@ -27,7 +26,7 @@ public class Authentication implements En {
public Authentication(Context context) {
Utils utils = context.getUtils();
- Given("^I am a user$", () -> context.setUser(UUID.randomUUID().toString()));
+ Given("^I am a user$", () -> context.setUser("test"));
Given("^I have an account at Central EGA$", () -> {
DockerClient dockerClient = utils.getDockerClient();
@@ -107,12 +106,6 @@ public Authentication(Context context) {
}
private void authenticate(Context context) {
- // need to retry twice due to bug in SSHJ library
- retryAuthenticationAttempt(context);
- retryAuthenticationAttempt(context);
- }
-
- private void retryAuthenticationAttempt(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
From 8f82b3eefc6e60e71d676c60e15f6e6cbb09670c Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 21:26:01 +0100
Subject: [PATCH 084/528] Change keys permissions in code, run tests as root.
---
.travis.yml | 2 +-
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 8 ++++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 9df1eb2c..05c838cc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,7 +18,7 @@ install:
script:
- cd ../tests
- - mvn test -B
+ - sudo mvn test -B
after_success:
- |
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 1dfba558..76de69d7 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -16,8 +16,11 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
+import java.util.Collections;
import java.util.UUID;
@Slf4j
@@ -46,7 +49,6 @@ public Authentication(Context context) {
String user = context.getUser();
utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
- utils.executeWithinContainer(tempWorker, String.format("chmod 400 /%s/%s.sec", dataFolderName, user).split(" "));
String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
@@ -110,7 +112,9 @@ private void authenticate(Context context) {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
- ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
+ File privateKey = context.getPrivateKey();
+ Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
+ ssh.authPublickey(context.getUser(), privateKey.getPath());
context.setSftp(ssh.newSFTPClient());
context.setAuthenticationFailed(false);
} catch (Exception e) {
From 55023ae5df09e1cc8e67690515042e19b822fcf2 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sun, 5 Nov 2017 13:20:12 +0100
Subject: [PATCH 085/528] Cleanup inbox after tests execution.
---
.../java/se/nbis/lega/cucumber/Context.java | 2 ++
.../java/se/nbis/lega/cucumber/Utils.java | 17 ++++++++++--
.../lega/cucumber/hooks/BeforeAfterHooks.java | 9 ++++---
.../lega/cucumber/steps/Authentication.java | 26 ++++++++++++-------
4 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Context.java b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
index d7819dfd..11fe73a0 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Context.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
@@ -1,6 +1,7 @@
package se.nbis.lega.cucumber;
import lombok.Data;
+import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.sftp.SFTPClient;
import java.io.File;
@@ -14,6 +15,7 @@ public class Context {
private File privateKey;
private String cegaMQUser;
private String cegaMQPassword;
+ private SSHClient ssh;
private SFTPClient sftp;
private File dataFolder;
private File rawFile;
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index 0a0e9e65..c650892a 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -71,11 +71,24 @@ public String executeDBQuery(String query) throws IOException, InterruptedExcept
return executeWithinContainer(findContainer("nbis/ega:db", "ega_db"), "psql", "-U", readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
}
+ /**
+ * Checks if user exists in the local database.
+ *
+ * @param user Username.
+ * @return true
if user exists, false
otherwise.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public boolean isUserExistInDB(String user) throws IOException, InterruptedException {
+ String output = executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", user));
+ return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
+ }
+
/**
* Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
*
- * @param from Folder to mount from.
- * @param to Folder to mount to.
+ * @param from Folder to mount from.
+ * @param to Folder to mount to.
* @param command Command to execute.
* @throws InterruptedException In case the command execution is interrupted.
*/
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index bbf24f9f..b685ff08 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -5,9 +5,9 @@
import cucumber.api.java8.En;
import org.apache.commons.io.FileUtils;
import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
import java.io.File;
-import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Paths;
@@ -36,8 +36,11 @@ public void tearDown() throws IOException, InterruptedException {
FileUtils.deleteDirectory(context.getDataFolder());
String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
File cegaUsersFolder = new File(cegaUsersFolderPath);
- Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
- context.getUtils().executeDBQuery(String.format("delete from users where elixir_id = '%s'", context.getUser()));
+ Utils utils = context.getUtils();
+ String user = context.getUser();
+ Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
+ utils.executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ utils.executeWithinContainer(utils.findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 76de69d7..7fb7d6f1 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -66,7 +66,8 @@ public Authentication(Context context) {
() -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
When("^my account expires$", () -> {
- authenticate(context);
+ connect(context);
+ disconnect(context);
try {
Thread.sleep(1000);
utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
@@ -76,14 +77,12 @@ public Authentication(Context context) {
});
When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
- authenticate(context);
+ connect(context);
});
Then("^I am in the local database$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
- String count = output.split(System.getProperty("line.separator"))[2];
- Assert.assertEquals(1, Integer.parseInt(count.trim()));
+ Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -92,9 +91,7 @@ public Authentication(Context context) {
Then("^I am not in the local database$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
- String count = output.split(System.getProperty("line.separator"))[2];
- Assert.assertEquals(0, Integer.parseInt(count.trim()));
+ Assert.assertFalse(utils.isUserExistInDB(context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -107,7 +104,7 @@ public Authentication(Context context) {
}
- private void authenticate(Context context) {
+ private void connect(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
@@ -115,6 +112,8 @@ private void authenticate(Context context) {
File privateKey = context.getPrivateKey();
Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
ssh.authPublickey(context.getUser(), privateKey.getPath());
+
+ context.setSsh(ssh);
context.setSftp(ssh.newSFTPClient());
context.setAuthenticationFailed(false);
} catch (Exception e) {
@@ -123,4 +122,13 @@ private void authenticate(Context context) {
}
}
+ private void disconnect(Context context) {
+ try {
+ context.getSftp().close();
+ context.getSsh().disconnect();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+
}
\ No newline at end of file
From f9c69c370d6b55eeb2f10f2f2ce54c23034322f0 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Tue, 7 Nov 2017 12:35:59 +0100
Subject: [PATCH 086/528] Refactoring.
---
.../java/se/nbis/lega/cucumber/Utils.java | 24 ++++++++++++++++++-
.../lega/cucumber/hooks/BeforeAfterHooks.java | 4 ++--
.../lega/cucumber/steps/Authentication.java | 11 +++++++++
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index c650892a..bd0cf5b0 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -72,7 +72,7 @@ public String executeDBQuery(String query) throws IOException, InterruptedExcept
}
/**
- * Checks if user exists in the local database.
+ * Checks if the user exists in the local database.
*
* @param user Username.
* @return true
if user exists, false
otherwise.
@@ -84,6 +84,28 @@ public boolean isUserExistInDB(String user) throws IOException, InterruptedExcep
return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
}
+ /**
+ * Removes the user from the local database.
+ *
+ * @param user Username.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public void removeUserFromDB(String user) throws IOException, InterruptedException {
+ executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ }
+
+ /**
+ * Removes the user from the inbox.
+ *
+ * @param user Username.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public void removeUserFromInbox(String user) throws IOException, InterruptedException {
+ executeWithinContainer(findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ }
+
/**
* Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
*
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index b685ff08..aba27ac2 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -39,8 +39,8 @@ public void tearDown() throws IOException, InterruptedException {
Utils utils = context.getUtils();
String user = context.getUser();
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
- utils.executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
- utils.executeWithinContainer(utils.findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ utils.removeUserFromDB(user);
+ utils.removeUserFromInbox(user);
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 7fb7d6f1..57b5dd40 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -5,6 +5,7 @@
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Volume;
+import cucumber.api.PendingException;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
@@ -80,6 +81,16 @@ public Authentication(Context context) {
connect(context);
});
+ When("^inbox is not created for me$", () -> {
+ try {
+ disconnect(context);
+ utils.removeUserFromInbox(context.getUser());
+ connect(context);
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
+
Then("^I am in the local database$", () -> {
try {
Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
From 74a440300ff3322acc5baa82e8318651f1c24708 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Thu, 9 Nov 2017 22:51:09 +0100
Subject: [PATCH 087/528] Align tests with new multi-ega functionality.
---
.../java/se/nbis/lega/cucumber/Context.java | 5 ++
.../java/se/nbis/lega/cucumber/Utils.java | 57 ++++++++-----
.../lega/cucumber/hooks/BeforeAfterHooks.java | 11 ++-
.../lega/cucumber/steps/Authentication.java | 83 +++++++++++--------
.../nbis/lega/cucumber/steps/Ingestion.java | 18 ++--
.../nbis/lega/cucumber/steps/Uploading.java | 8 +-
.../cucumber/features/authentication.feature | 20 +++--
.../cucumber/features/ingestion.feature | 4 +-
.../cucumber/features/uploading.feature | 4 +-
9 files changed, 132 insertions(+), 78 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Context.java b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
index 11fe73a0..b67b4b75 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Context.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
@@ -5,6 +5,7 @@
import net.schmizz.sshj.sftp.SFTPClient;
import java.io.File;
+import java.util.List;
@Data
public class Context {
@@ -12,9 +13,13 @@ public class Context {
private Utils utils = new Utils();
private String user;
+ private List instances;
+ private String targetInstance;
private File privateKey;
private String cegaMQUser;
private String cegaMQPassword;
+ private String cegaMQVHost;
+ private String routingKey;
private SSHClient ssh;
private SFTPClient sftp;
private File dataFolder;
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index bd0cf5b0..2d016ebf 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -35,6 +35,15 @@ public Utils() {
this.dockerClient = DockerClientBuilder.getInstance(DefaultDockerClientConfig.createDefaultConfigBuilder().build()).build();
}
+ /**
+ * Gets absolute path or a private folder.
+ *
+ * @return Absolute path or a private folder.
+ */
+ public String getPrivateFolderPath() {
+ return Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private";
+ }
+
/**
* Executes shell command within specified container.
*
@@ -62,66 +71,71 @@ public String executeWithinContainer(Container container, String... command) thr
/**
* Executes PSQL query.
*
- * @param query Query to execute.
+ * @param instance LocalEGA site.
+ * @param query Query to execute.
* @return Query output.
* @throws IOException In case of output error.
* @throws InterruptedException In case the query execution is interrupted.
*/
- public String executeDBQuery(String query) throws IOException, InterruptedException {
- return executeWithinContainer(findContainer("nbis/ega:db", "ega_db"), "psql", "-U", readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
+ public String executeDBQuery(String instance, String query) throws IOException, InterruptedException {
+ return executeWithinContainer(findContainer("nbisweden/ega-db", "ega_db_" + instance), "psql", "-U", readTraceProperty(instance, "DB_USER"), "-d", "lega", "-c", query);
}
/**
* Checks if the user exists in the local database.
*
- * @param user Username.
+ * @param instance LocalEGA site.
+ * @param user Username.
* @return true
if user exists, false
otherwise.
* @throws IOException In case of output error.
* @throws InterruptedException In case the query execution is interrupted.
*/
- public boolean isUserExistInDB(String user) throws IOException, InterruptedException {
- String output = executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", user));
+ public boolean isUserExistInDB(String instance, String user) throws IOException, InterruptedException {
+ String output = executeDBQuery(instance, String.format("select count(*) from users where elixir_id = '%s'", user));
return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
}
/**
* Removes the user from the local database.
*
- * @param user Username.
+ * @param instance LocalEGA site.
+ * @param user Username.
* @throws IOException In case of output error.
* @throws InterruptedException In case the query execution is interrupted.
*/
- public void removeUserFromDB(String user) throws IOException, InterruptedException {
- executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ public void removeUserFromDB(String instance, String user) throws IOException, InterruptedException {
+ executeDBQuery(instance, String.format("delete from users where elixir_id = '%s'", user));
}
/**
* Removes the user from the inbox.
*
- * @param user Username.
+ * @param instance LocalEGA site.
+ * @param user Username.
* @throws IOException In case of output error.
* @throws InterruptedException In case the query execution is interrupted.
*/
- public void removeUserFromInbox(String user) throws IOException, InterruptedException {
- executeWithinContainer(findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ public void removeUserFromInbox(String instance, String user) throws IOException, InterruptedException {
+ executeWithinContainer(findContainer("nbisweden/ega-inbox", "ega_inbox_" + instance), String.format("rm -rf /ega/inbox/%s", user).split(" "));
}
/**
- * Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
+ * Spawns "nbisweden/ega-worker" container, mounts data folder there and executes a command.
*
- * @param from Folder to mount from.
- * @param to Folder to mount to.
- * @param command Command to execute.
+ * @param instance LocalEGA site.
+ * @param from Folder to mount from.
+ * @param to Folder to mount to.
+ * @param command Command to execute.
* @throws InterruptedException In case the command execution is interrupted.
*/
- public void spawnWorkerAndExecute(String from, String to, String... command) throws InterruptedException {
+ public void spawnWorkerAndExecute(String instance, String from, String to, String... command) throws InterruptedException {
Volume dataVolume = new Volume(to);
Volume gpgVolume = new Volume("/root/.gnupg");
CreateContainerResponse createContainerResponse = dockerClient.
- createContainerCmd("nbis/ega:worker").
+ createContainerCmd("nbisweden/ega-worker").
withVolumes(dataVolume, gpgVolume).
withBinds(new Bind(from, dataVolume),
- new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
+ new Bind(String.format("%s/%s/gpg", getPrivateFolderPath(), instance), gpgVolume, AccessMode.ro)).
withCmd(command).
exec();
dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
@@ -134,12 +148,13 @@ public void spawnWorkerAndExecute(String from, String to, String... command) thr
/**
* Reads property from the trace file.
*
+ * @param instance LocalEGA site.
* @param property Property name.
* @return Property value.
* @throws IOException In case it's not possible to read trace file.
*/
- public String readTraceProperty(String fileName, String property) throws IOException {
- File trace = new File(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/" + fileName);
+ public String readTraceProperty(String instance, String property) throws IOException {
+ File trace = new File(getPrivateFolderPath() + "/.trace." + instance);
return FileUtils.readLines(trace, Charset.defaultCharset()).
stream().
filter(l -> l.startsWith(property)).
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index aba27ac2..c68e4631 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -10,7 +10,6 @@
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
-import java.nio.file.Paths;
import java.util.Arrays;
public class BeforeAfterHooks implements En {
@@ -33,14 +32,14 @@ public void setUp() throws IOException {
@After
public void tearDown() throws IOException, InterruptedException {
- FileUtils.deleteDirectory(context.getDataFolder());
- String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
- File cegaUsersFolder = new File(cegaUsersFolderPath);
Utils utils = context.getUtils();
+ FileUtils.deleteDirectory(context.getDataFolder());
+ String targetInstance = context.getTargetInstance();
+ File cegaUsersFolder = new File(utils.getPrivateFolderPath() + "/cega/users/" + targetInstance);
String user = context.getUser();
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
- utils.removeUserFromDB(user);
- utils.removeUserFromInbox(user);
+ utils.removeUserFromDB(targetInstance, user);
+ utils.removeUserFromInbox(targetInstance, user);
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 57b5dd40..0b4cad36 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -5,7 +5,7 @@
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Volume;
-import cucumber.api.PendingException;
+import cucumber.api.DataTable;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
@@ -18,7 +18,6 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
-import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
import java.util.Collections;
@@ -30,48 +29,65 @@ public class Authentication implements En {
public Authentication(Context context) {
Utils utils = context.getUtils();
- Given("^I am a user$", () -> context.setUser("test"));
+ Given("^I am a user of LocalEGA instances:$", (DataTable instances) -> {
+ context.setUser("test");
+ context.setInstances(instances.asList(String.class));
+ });
Given("^I have an account at Central EGA$", () -> {
- DockerClient dockerClient = utils.getDockerClient();
- String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
- String name = UUID.randomUUID().toString();
- String dataFolderName = context.getDataFolder().getName();
- CreateContainerResponse createContainerResponse = dockerClient.
- createContainerCmd("nbis/ega:worker").
- withName(name).
- withCmd("sleep", "1000").
- withBinds(new Bind(cegaUsersFolderPath, new Volume("/" + dataFolderName))).
- exec();
- dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
- try {
- Container tempWorker = utils.findContainer("nbis/ega:worker", name);
- double password = Math.random();
- String user = context.getUser();
- utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
- utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
- String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
- File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
- FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
- } catch (IOException | InterruptedException e) {
- log.error(e.getMessage(), e);
- } finally {
- dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
+ for (String instance : context.getInstances()) {
+ DockerClient dockerClient = utils.getDockerClient();
+ String cegaUsersFolderPath = utils.getPrivateFolderPath() + "/cega/users/" + instance;
+ String name = UUID.randomUUID().toString();
+ String dataFolderName = context.getDataFolder().getName();
+ CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerCmd("nbisweden/ega-worker").
+ withName(name).
+ withCmd("sleep", "1000").
+ withBinds(new Bind(cegaUsersFolderPath, new Volume("/" + dataFolderName))).
+ exec();
+ dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
+ try {
+ Container tempWorker = utils.findContainer("nbisweden/ega-worker", name);
+ double password = Math.random();
+ String user = context.getUser();
+ String opensslCommand = utils.readTraceProperty(instance, "OPENSSL exec");
+ utils.executeWithinContainer(tempWorker, String.format("%s genrsa -out /%s/%s.sec -passout pass:%f 2048", opensslCommand, dataFolderName, user, password).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("%s rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", opensslCommand, dataFolderName, user, password, dataFolderName, user).split(" "));
+ String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
+ File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
+ FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ } finally {
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
+ }
}
});
+ Given("^I want to work with instance \"([^\"]*)\"$", context::setTargetInstance);
+
Given("^I have correct private key$",
- () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", context.getUser()))));
+ () -> {
+ try {
+ File privateKey = new File(String.format("%s/cega/users/%s/%s.sec", utils.getPrivateFolderPath(), context.getTargetInstance(), context.getUser()));
+ Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
+ context.setPrivateKey(privateKey);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
Given("^I have incorrect private key$",
- () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
+ () -> context.setPrivateKey(new File(String.format("%s/cega/users/%s.sec", utils.getPrivateFolderPath(), "john"))));
When("^my account expires$", () -> {
connect(context);
disconnect(context);
try {
Thread.sleep(1000);
- utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
+ utils.executeDBQuery(context.getTargetInstance(),
+ String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
}
@@ -84,7 +100,7 @@ public Authentication(Context context) {
When("^inbox is not created for me$", () -> {
try {
disconnect(context);
- utils.removeUserFromInbox(context.getUser());
+ utils.removeUserFromInbox(context.getTargetInstance(), context.getUser());
connect(context);
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
@@ -93,7 +109,7 @@ public Authentication(Context context) {
Then("^I am in the local database$", () -> {
try {
- Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
+ Assert.assertTrue(utils.isUserExistInDB(context.getTargetInstance(), context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -102,7 +118,7 @@ public Authentication(Context context) {
Then("^I am not in the local database$", () -> {
try {
- Assert.assertFalse(utils.isUserExistInDB(context.getUser()));
+ Assert.assertFalse(utils.isUserExistInDB(context.getTargetInstance(), context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -121,7 +137,6 @@ private void connect(Context context) {
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
File privateKey = context.getPrivateKey();
- Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
ssh.authPublickey(context.getUser(), privateKey.getPath());
context.setSsh(ssh);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
index 3560a8d7..4d839506 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -18,8 +18,10 @@ public Ingestion(Context context) {
Given("^I have CEGA username and password$", () -> {
try {
- context.setCegaMQUser(utils.readTraceProperty("CEGA_MQ_USER"));
- context.setCegaMQPassword(utils.readTraceProperty("CEGA_MQ_PASSWORD"));
+ context.setCegaMQUser(utils.readTraceProperty(context.getTargetInstance(), "CEGA_MQ_USER"));
+ context.setCegaMQPassword(utils.readTraceProperty(context.getTargetInstance(), "CEGA_MQ_PASSWORD"));
+ context.setCegaMQVHost(context.getTargetInstance());
+ context.setRoutingKey(context.getTargetInstance());
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -29,11 +31,12 @@ public Ingestion(Context context) {
When("^I ingest file from the LocalEGA inbox$", () -> {
try {
File encryptedFile = context.getEncryptedFile();
- utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "cega_mq"),
- String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
+ utils.executeWithinContainer(utils.findContainer("nbisweden/ega-cega_mq", "cega_mq"),
+ String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s %s --unenc %s --enc %s",
context.getCegaMQUser(),
context.getCegaMQPassword(),
- utils.readTraceProperty("CEGA_MQ_VHOST"),
+ context.getCegaMQVHost(),
+ context.getRoutingKey(),
context.getUser(),
encryptedFile.getName(),
utils.calculateMD5(context.getRawFile()),
@@ -47,9 +50,10 @@ public Ingestion(Context context) {
Then("^the file is ingested successfully$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName()));
+ String output = utils.executeDBQuery(context.getTargetInstance(),
+ String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName()));
String vaultFileName = output.split(System.getProperty("line.separator"))[2];
- String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "ega_vault"), "cat", vaultFileName.trim());
+ String cat = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-common", "ega_vault"), "cat", vaultFileName.trim());
Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index dcae27d6..21bd51d4 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -31,12 +31,14 @@ public Uploading(Context context) {
Volume gpgVolume = new Volume("/root/.gnupg");
CreateContainerResponse createContainerResponse = null;
try {
+ String targetInstance = context.getTargetInstance();
+ String gpgCommand = utils.readTraceProperty(targetInstance, "GPG exec");
createContainerResponse = dockerClient.
- createContainerCmd("nbis/ega:worker").
+ createContainerCmd("nbisweden/ega-worker").
withVolumes(dataVolume, gpgVolume).
withBinds(new Bind(Paths.get(dataFolderName).toAbsolutePath().toString(), dataVolume),
- new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
- withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", String.format("/%s/%s.enc", dataFolderName, rawFile.getName()), String.format("/%s/%s", dataFolderName, rawFile.getName())).
+ new Bind(String.format("%s/%s/gpg", utils.getPrivateFolderPath(), targetInstance), gpgVolume, AccessMode.ro)).
+ withCmd(gpgCommand, "-r", utils.readTraceProperty(targetInstance, "GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
exec();
} catch (IOException e) {
log.error(e.getMessage(), e);
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index 166d0211..78f416a0 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -2,35 +2,45 @@ Feature: Authentication
As a user I want to be able to authenticate against LocalEGA inbox
Scenario: User population in LocalEGA DB from Central EGA
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then I am in the local database
Scenario: User doesn't exist in Central EGA, but tries to authenticate against LocalEGA inbox
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
+ And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
Scenario: User exists in Central EGA, but uses incorrect private key for authentication
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have incorrect private key
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
Scenario: User exists in Central EGA, but his account has expired
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
When my account expires
Then I am not in the local database
Scenario: User exists in Central EGA and uses correct private key for authentication
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then I'm logged in successfully
\ No newline at end of file
diff --git a/tests/src/test/resources/cucumber/features/ingestion.feature b/tests/src/test/resources/cucumber/features/ingestion.feature
index 52804f16..529f12fe 100644
--- a/tests/src/test/resources/cucumber/features/ingestion.feature
+++ b/tests/src/test/resources/cucumber/features/ingestion.feature
@@ -2,8 +2,10 @@ Feature: Ingestion
As a user I want to be able to ingest files from the LocalEGA inbox
Scenario: Ingest files from the LocalEGA inbox
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
diff --git a/tests/src/test/resources/cucumber/features/uploading.feature b/tests/src/test/resources/cucumber/features/uploading.feature
index 9adf5c3c..f7bf08b1 100644
--- a/tests/src/test/resources/cucumber/features/uploading.feature
+++ b/tests/src/test/resources/cucumber/features/uploading.feature
@@ -2,8 +2,10 @@ Feature: Uploading
As a user I want to be able to upload files to the LocalEGA inbox
Scenario: Upload files to the LocalEGA inbox
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
From 2f708bc52e972baea4259ab8f9ff2e8a40669a55 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Fri, 10 Nov 2017 13:32:03 +0100
Subject: [PATCH 088/528] Add inbox removal test.
---
.../lega/cucumber/steps/Authentication.java | 14 ++++--
.../cucumber/features/authentication.feature | 47 ++++++++++++-------
2 files changed, 40 insertions(+), 21 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 0b4cad36..59bdf4b2 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -81,6 +81,14 @@ public Authentication(Context context) {
Given("^I have incorrect private key$",
() -> context.setPrivateKey(new File(String.format("%s/cega/users/%s.sec", utils.getPrivateFolderPath(), "john"))));
+ Given("^Inbox is deleted for my user$", () -> {
+ try {
+ utils.removeUserFromInbox(context.getTargetInstance(), context.getUser());
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
+
When("^my account expires$", () -> {
connect(context);
disconnect(context);
@@ -93,9 +101,9 @@ public Authentication(Context context) {
}
});
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
- connect(context);
- });
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> connect(context));
+
+ When("^I disconnect from the LocalEGA inbox$", () -> disconnect(context));
When("^inbox is not created for me$", () -> {
try {
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index 78f416a0..d4808e1f 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -1,45 +1,56 @@
Feature: Authentication
As a user I want to be able to authenticate against LocalEGA inbox
- Scenario: User population in LocalEGA DB from Central EGA
+ Background:
Given I am a user of LocalEGA instances:
| swe1 |
- And I have an account at Central EGA
+
+ Scenario: User population in LocalEGA DB from Central EGA
+ Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then I am in the local database
Scenario: User doesn't exist in Central EGA, but tries to authenticate against LocalEGA inbox
- Given I am a user of LocalEGA instances:
- | swe1 |
+ Given I want to work with instance "swe1"
+ And I have correct private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
+ Scenario: User exists in Central EGA, but his account has expired
+ Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have correct private key
+ When my account expires
+ Then I am not in the local database
+
+ Scenario: User exists in Central EGA and tries to connect to LocalEGA, but the inbox was not created for him
+ Given I have an account at Central EGA
+ And I want to work with instance "swe1"
+ And I have correct private key
+ And I connect to the LocalEGA inbox via SFTP using private key
+ And I disconnect from the LocalEGA inbox
+ And Inbox is deleted for my user
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
Scenario: User exists in Central EGA, but uses incorrect private key for authentication
- Given I am a user of LocalEGA instances:
- | swe1 |
- And I have an account at Central EGA
+ Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have incorrect private key
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
- Scenario: User exists in Central EGA, but his account has expired
- Given I am a user of LocalEGA instances:
- | swe1 |
- And I have an account at Central EGA
- And I want to work with instance "swe1"
+ Scenario: User exists in Central EGA and uses correct private key for authentication, but the wrong instance
+ Given I have an account at Central EGA
+ And I want to work with instance "fin1"
And I have correct private key
- When my account expires
- Then I am not in the local database
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
- Scenario: User exists in Central EGA and uses correct private key for authentication
- Given I am a user of LocalEGA instances:
- | swe1 |
- And I have an account at Central EGA
+ Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance
+ Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
From c638fd4195f633134a12f9fd63a6622e3caa15ae Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Fri, 10 Nov 2017 13:55:50 +0100
Subject: [PATCH 089/528] Add "database down" test.
---
tests/src/test/java/se/nbis/lega/cucumber/Utils.java | 2 +-
.../se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java | 9 +++++++++
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 5 +++++
.../resources/cucumber/features/authentication.feature | 8 ++++++++
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index 2d016ebf..b66a2f23 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -170,7 +170,7 @@ public String readTraceProperty(String instance, String property) throws IOExcep
* @return Docker container.
*/
public Container findContainer(String imageName, String containerName) {
- return dockerClient.listContainersCmd().exec().
+ return dockerClient.listContainersCmd().withShowAll(true).exec().
stream().
filter(c -> c.getImage().equals(imageName)).
filter(c -> ArrayUtils.contains(c.getNames(), "/" + containerName)).
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index c68e4631..b5a40ab6 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -1,5 +1,7 @@
package se.nbis.lega.cucumber.hooks;
+import com.github.dockerjava.api.exception.NotModifiedException;
+import com.github.dockerjava.api.model.Container;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java8.En;
@@ -33,6 +35,13 @@ public void setUp() throws IOException {
@After
public void tearDown() throws IOException, InterruptedException {
Utils utils = context.getUtils();
+
+ try { // bring DB back in case it's gone down
+ Container dbContainer = utils.findContainer("nbisweden/ega-db", "ega_db_" + context.getTargetInstance());
+ utils.getDockerClient().startContainerCmd(dbContainer.getId()).exec();
+ } catch (NotModifiedException e) {
+ }
+
FileUtils.deleteDirectory(context.getDataFolder());
String targetInstance = context.getTargetInstance();
File cegaUsersFolder = new File(utils.getPrivateFolderPath() + "/cega/users/" + targetInstance);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 59bdf4b2..9f6eddec 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -89,6 +89,11 @@ public Authentication(Context context) {
}
});
+ Given("^database is down$", () -> {
+ Container dbContainer = utils.findContainer("nbisweden/ega-db", "ega_db_" + context.getTargetInstance());
+ utils.getDockerClient().stopContainerCmd(dbContainer.getId()).exec();
+ });
+
When("^my account expires$", () -> {
connect(context);
disconnect(context);
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index d4808e1f..6338edd8 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -49,6 +49,14 @@ Feature: Authentication
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
+ Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance, but database is down
+ Given I have an account at Central EGA
+ And I want to work with instance "swe1"
+ And I have correct private key
+ And database is down
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance
Given I have an account at Central EGA
And I want to work with instance "swe1"
From f98a33e6716518568e3303aa85cb78763b0719e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Sat, 11 Nov 2017 07:43:29 +0100
Subject: [PATCH 090/528] Bootstrap in one
---
.travis.yml | 3 +-
docker/Makefile | 19 ++
docker/README.md | 18 +-
docker/bootstrap/README.md | 55 ----
docker/bootstrap/boot.sh | 79 +++++-
docker/bootstrap/cega.sh | 262 -------------------
docker/bootstrap/defaults/cega | 17 --
docker/bootstrap/generate.sh | 211 ---------------
docker/bootstrap/info.md | 57 ----
docker/bootstrap/lib.sh | 73 ------
docker/bootstrap/populate.sh | 117 ---------
docker/bootstrap/{defaults => settings}/fin1 | 7 +-
docker/bootstrap/{defaults => settings}/swe1 | 7 +-
docker/bootstrap/troubleshooting.md | 17 ++
docker/bootstrap/yourself.md | 110 --------
docker/ega.yml | 36 +--
docker/images/Makefile | 6 +-
docker/images/worker/Dockerfile | 30 ++-
18 files changed, 169 insertions(+), 955 deletions(-)
create mode 100644 docker/Makefile
delete mode 100644 docker/bootstrap/README.md
delete mode 100755 docker/bootstrap/cega.sh
delete mode 100644 docker/bootstrap/defaults/cega
delete mode 100755 docker/bootstrap/generate.sh
delete mode 100644 docker/bootstrap/info.md
delete mode 100644 docker/bootstrap/lib.sh
delete mode 100755 docker/bootstrap/populate.sh
rename docker/bootstrap/{defaults => settings}/fin1 (67%)
rename docker/bootstrap/{defaults => settings}/swe1 (67%)
create mode 100644 docker/bootstrap/troubleshooting.md
delete mode 100644 docker/bootstrap/yourself.md
diff --git a/.travis.yml b/.travis.yml
index 9df1eb2c..281ba939 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,8 +9,7 @@ before_install:
- |
cd docker
make -C images -j 4
- docker run --rm -i -v ${PWD}/bootstrap:/ega nbisweden/ega-worker /ega/boot.sh
- bootstrap/populate.sh
+ make bootstrap
sudo chown -R $USER .
install:
diff --git a/docker/Makefile b/docker/Makefile
new file mode 100644
index 00000000..b52f0d92
--- /dev/null
+++ b/docker/Makefile
@@ -0,0 +1,19 @@
+
+.PHONY: all bootstrap
+
+all: up
+
+.env private:
+ @docker run --rm -it --name ega_bootstrap -v ${PWD}:/ega nbisweden/ega-worker /ega/bootstrap/boot.sh
+
+bootstrap: .env private
+
+up: .env private
+ @docker-compose up -d
+
+down: #.env
+ @docker-compose down -v
+
+clean:
+ rm -rf .env private
+
diff --git a/docker/README.md b/docker/README.md
index 48981cd2..abd22c96 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -6,19 +6,19 @@ First [create the EGA docker images](images) beforehand, with `make -C images`.
You can then [generate the private data](bootstrap), with either:
- docker run --rm -it -v ${PWD}/bootstrap:/ega nbisweden/ega-worker /ega/boot.sh
-
+ make bootstrap
+
> Note: you can run `bootstrap/boot.sh` on your host machine but
> you need the required tools installed, including Python 3.6, GnuPG
-> 2.2.2, OpenSSL, `readlink`, `xxd`, ...
-
-You can afterwards copy the settings into place with
-
- bootstrap/populate.sh
+> 2.2.2, OpenSSL 1.0.2, `readlink`, `xxd`, ...
-The passwords are in `bootstrap/private/.trace.*` and the errors (if any) are in `bootstrap/.err`.
+The command will create a `.env` file and a `private` folder holding
+the necessary data (ie the GnuPG key, the RSA master key pair, the SSL
+certificates for internal communication, passwords, default users,
+etc...)
-Alternatively, you can setup all [configuration files by hand](bootstrap/yourself.md).
+The passwords are in `private//.trace` and the errors (if
+any) are in `private/.err`.
# Running
diff --git a/docker/bootstrap/README.md b/docker/bootstrap/README.md
deleted file mode 100644
index f895153d..00000000
--- a/docker/bootstrap/README.md
+++ /dev/null
@@ -1,55 +0,0 @@
-The following is not technically part of LocalEGA but it can useful to
-get started on it.
-
-We have created 2 bash scripts, one for the generation of the GnuPG
-key, RSA master key pair, SSL certificates for internal communication,
-passwords, default users, etc...
-
-Use `-h` to see the possible options of each script.
-
-We create a separate folder and generate all the necessary files in it (require
-GnuPG 2.2.1, OpenSSL 1.0.2 and Python 3.6.1). Note that potential error
-messages can be found at the file `.err` in the same folder.
-
- ./cega.sh
- ./generate.sh --
-
-We then move the `.env` and `.env.d/` into place (backing them up in the
-destination location if there was already a version)
-
- ./populate.sh
-
-The passwords are in `private/.trace.*` (if you did not use `--private_dir`)
-
-If you don't have the required tools installed on your machine (namely
-GnuPG 2.2.2, OpenSSL 1.0.2 and Python 3.6.1), you can use the `nbisweden/ega-worker:latest`
-image that you have built up with the `make` command in the [images](../images) folder:
-
-In the same folder as `generate.sh`, run
-
- docker run --rm -it -v ${PWD}:/ega nbisweden/ega-worker /ega/generate.sh -- swe1
-
-That will create a folder, named 'private', with all the settings
-After that, you can run `./populate.sh` to move the `.env` and `.env.d/` into
-their destination
-
-
-Alternatively, albeit not recommended, you
-can [generate the private data yourself](info.md), and adapt the
-different PATHs in the `.env` and `.env.d` settings.
-
-
-## Troubleshooting
-
-* If the commands `./cega.sh` and `./generate.sh` take more than a
- few seconds to run, it is usually because your computer does not
- have enough entropy. You can use the program `rng-tools` to solve
- this problem. E.g. on Debian/Ubuntu system, install the software by
-
- sudo apt-get install rng-tools
-
- and then run
-
- sudo rngd -r /dev/urandom
-
-
diff --git a/docker/bootstrap/boot.sh b/docker/bootstrap/boot.sh
index 94729b2f..1b622406 100755
--- a/docker/bootstrap/boot.sh
+++ b/docker/bootstrap/boot.sh
@@ -1,9 +1,78 @@
#!/usr/bin/env bash
set -e
-SCRIPT=$(dirname ${BASH_SOURCE[0]})
-HERE=$PWD/${SCRIPT#./}
+HERE=$(dirname ${BASH_SOURCE[0]})
+PRIVATE=${HERE}/../private
+DOT_ENV=${HERE}/../.env
+LIB=${HERE}/lib
+SETTINGS=${HERE}/settings
-$HERE/cega.sh $@
-$HERE/generate.sh $@ -- swe1
-$HERE/generate.sh $@ -- fin1
+# Defaults
+VERBOSE=no
+FORCE=yes
+OPENSSL=openssl
+GPG=gpg
+GPG_CONF=gpgconf
+
+function usage {
+ echo "Usage: $0 [options]"
+ echo -e "\nOptions are:"
+ echo -e "\t--openssl \tPath to the Openssl executable [Default: ${OPENSSL}]"
+ echo -e "\t--gpg \tPath to the GnuPG executable [Default: ${GPG}]"
+ echo -e "\t--gpgconf \tPath to the GnuPG conf executable [Default: ${GPG_CONF}]"
+ echo ""
+ echo -e "\t--verbose, -v \tShow verbose output"
+ echo -e "\t--polite, -p \tDo not force the re-creation of the subfolders. Ask instead"
+ echo -e "\t--help, -h \tOutputs this message and exits"
+ echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
+ echo ""
+}
+
+# While there are arguments or '--' is reached
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --help|-h) usage; exit 0;;
+ --verbose|-v) VERBOSE=yes;;
+ --polite|-p) FORCE=no;;
+ --gpg) GPG=$2; shift;;
+ --gpgconf) GPG_CONF=$2; shift;;
+ --openssl) OPENSSL=$2; shift;;
+ --) shift; break;;
+ *) echo "$0: error - unrecognized option $1" 1>&2; usage; exit 1;; esac
+ shift
+done
+
+[[ $VERBOSE == 'no' ]] && echo -en "Bootstrapping "
+
+source ${LIB}/defs.sh
+
+INSTANCES=$(ls ${SETTINGS} | xargs) # make it one line. ls -lx didn't work
+
+rm_politely ${PRIVATE}
+mkdir -p ${PRIVATE}/cega
+backup ${DOT_ENV}
+
+exec 2>${PRIVATE}/.err
+
+cat > ${DOT_ENV} <> ${PRIVATE}/cega/env <"
- echo -e "\nOptions are:"
- echo -e "\t--private_dir \tName of the main folder for private data"
- echo ""
- echo -e "\t--defaults \tDefaults data to be loaded [$DEFAULTS]"
- echo ""
- echo -e "\t--verbose, -v \tShow verbose output"
- echo -e "\t--polite, -p \tDo not force the re-creation of the subfolders. Ask instead"
- echo -e "\t--help, -h \tOutputs this message and exits"
- echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
- echo ""
-}
-
-# While there are arguments or '--' is reached
-while [[ $# -gt 0 ]]; do
- case "$1" in
- --help|-h) usage; exit 0;;
- --verbose|-v) VERBOSE=yes;;
- --polite|-p) FORCE=no;;
- --private_dir) PRIVATE=$2; shift;;
- --defaults) DEFAULTS=$2; shift;;
- --) shift; break;;
- *) echo "$0: error - unrecognized option $1" 1>&2; usage; exit 1;;
- esac
- shift
-done
-
-if [[ -e $DEFAULTS ]];then
- source $DEFAULTS
-else
- echo "Defaults not found"
- exit 1
-fi
-
-[[ $VERBOSE == 'yes' ]] && FORCE='no'
-exec 2>${HERE}/.err
-
-case $PRIVATE in
- /*) ABS_PRIVATE=$PRIVATE;;
- ./*|../*) ABS_PRIVATE=$PWD/$PRIVATE;;
- *) ABS_PRIVATE=$HERE/$PRIVATE;;
-esac
-
-[[ -x $(readlink ${OPENSSL}) ]] && echo "${OPENSSL} is not executable" && exit 3
-
-#########################################################################
-# And....cue music
-#########################################################################
-
-rm_politely $ABS_PRIVATE/cega
-mkdir -p $ABS_PRIVATE/cega/{users,mq}
-
-echo -n "Generating data for a fake Central EGA"
-
-echomsg "\t* fake EGA users"
-
-EGA_USER_PASSWORD_JOHN=$(generate_password 16)
-EGA_USER_PASSWORD_JANE=$(generate_password 16)
-EGA_USER_PASSWORD_TAYLOR=$(generate_password 16)
-
-EGA_USER_PUBKEY_JOHN=$ABS_PRIVATE/cega/users/john.pub
-EGA_USER_SECKEY_JOHN=$ABS_PRIVATE/cega/users/john.sec
-
-EGA_USER_PUBKEY_JANE=$ABS_PRIVATE/cega/users/jane.pub
-EGA_USER_SECKEY_JANE=$ABS_PRIVATE/cega/users/jane.sec
-
-
-${OPENSSL} genrsa -out ${EGA_USER_SECKEY_JOHN} -passout pass:${EGA_USER_PASSWORD_JOHN} 2048
-${OPENSSL} rsa -in ${EGA_USER_SECKEY_JOHN} -passin pass:${EGA_USER_PASSWORD_JOHN} -pubout -out ${EGA_USER_PUBKEY_JOHN}
-chmod 400 ${EGA_USER_SECKEY_JOHN}
-
-${OPENSSL} genrsa -out ${EGA_USER_SECKEY_JANE} -passout pass:${EGA_USER_PASSWORD_JANE} 2048
-${OPENSSL} rsa -in ${EGA_USER_SECKEY_JANE} -passin pass:${EGA_USER_PASSWORD_JANE} -pubout -out ${EGA_USER_PUBKEY_JANE}
-chmod 400 ${EGA_USER_SECKEY_JANE}
-
-
-cat > $ABS_PRIVATE/cega/users/john.yml < $ABS_PRIVATE/cega/users/jane.yml < $ABS_PRIVATE/cega/users/taylor.yml < $ABS_PRIVATE/cega/mq/defs.json < $ABS_PRIVATE/.env.d/cega_instances
-for i in "${!CEGA_REST[@]}"; do
- tmp=CEGA_REST_${i}_PASSWORD
- echo "${tmp}=${CEGA_REST[$i]}" >> $ABS_PRIVATE/.env.d/cega_instances
-done
-
-for i in "${!CEGA_REST[@]}"; do
- mkdir $ABS_PRIVATE/.env.d/$i
- cat > $ABS_PRIVATE/.env.d/$i/cega </$PRIVATE/cega/users/john.pub
-EGA_USER_PUBKEY_JANE = /$PRIVATE/cega/users/jane.pub
-EGA_USER_PASSWORD_TAYLOR = ${EGA_USER_PASSWORD_TAYLOR}
-# =============================
-EOF
-
- for i in "${!CEGA_MQ[@]}"; do
- echo -e "CEGA_MQ_${i}_PASSWORD = ${CEGA_MQ[$i]}"
- done
- echo -e "# ============================="
- for i in "${!CEGA_REST[@]}"; do
- echo -e "CEGA_REST_${i}_PASSWORD = ${CEGA_REST[$i]}"
- done
-
- for i in "${!CEGA_REST[@]}"; do
- echo "# ============================="
- echo "CEGA_ENDPOINT for $i"
- echo "# ============================="
- cat $ABS_PRIVATE/.env.d/$i/cega
- done
-} > $ABS_PRIVATE/.trace.cega
-#[[ $VERBOSE == 'yes' ]] && cat $ABS_PRIVATE/.trace.cega
diff --git a/docker/bootstrap/defaults/cega b/docker/bootstrap/defaults/cega
deleted file mode 100644
index e0cff552..00000000
--- a/docker/bootstrap/defaults/cega
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-OPENSSL=openssl
-LEGA_INSTANCES="swe1,fin1"
-
-declare -A CEGA_MQ
-CEGA_MQ['swe1']=$(generate_password 16)
-CEGA_MQ['fin1']=$(generate_password 16)
-
-declare -A CEGA_REST
-CEGA_REST['swe1']=$(generate_password 16)
-CEGA_REST['fin1']=$(generate_password 16)
-
-declare -A LEGA_GREETINGS
-LEGA_GREETINGS['swe1']="Welcome to Local EGA Sweden @ NBIS"
-LEGA_GREETINGS['fin1']="Welcome to Local EGA Finland @ CSC"
diff --git a/docker/bootstrap/generate.sh b/docker/bootstrap/generate.sh
deleted file mode 100755
index f34ccc0e..00000000
--- a/docker/bootstrap/generate.sh
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-SCRIPT=$(dirname ${BASH_SOURCE[0]})
-HERE=$PWD/${SCRIPT#./}
-
-source $HERE/lib.sh
-
-# Defaults
-VERBOSE=no
-FORCE=yes
-PRIVATE=private
-
-function usage {
- echo "Usage: $0 [options] -- "
- echo -e "\nOptions are:"
- echo -e "\t--private_dir \tName of the main folder for private data"
- echo ""
- echo -e "\t--verbose, -v \tShow verbose output"
- echo -e "\t--polite, -p \tDo not force the re-creation of the subfolders. Ask instead"
- echo -e "\t--help, -h \tOutputs this message and exits"
- echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
- echo ""
-}
-
-# While there are arguments or '--' is reached
-while [[ $# -gt 0 ]]; do
- case "$1" in
- --help|-h) usage; exit 0;;
- --verbose|-v) VERBOSE=yes;;
- --polite|-p) FORCE=no;;
- --private_dir) PRIVATE=$2; shift;;
- --) shift; break;;
- *) echo "$0: error - unrecognized option $1" 1>&2; usage; exit 1;;
- esac
- shift
-done
-
-[[ $VERBOSE == 'yes' ]] && FORCE='no'
-
-# Loading the instance's settings
-INSTANCE=$1
-[[ -z ${INSTANCE} ]] && usage && exit 1
-
-if [[ -f $HERE/defaults/$INSTANCE ]]; then
- source $HERE/defaults/$INSTANCE
-else
- echo "No settings found for $INSTANCE"
- exit 1
-fi
-
-#[[ $VERBOSE == 'no' ]] && exec 1>${HERE}/.log && FORCE='yes'
-exec 2>${HERE}/.err
-
-[[ -x $(readlink ${GPG}) ]] && echo "${GPG} is not executable" && exit 2
-[[ -x $(readlink ${OPENSSL}) ]] && echo "${OPENSSL} is not executable" && exit 3
-
-if [ -z "${DB_USER}" -o "${DB_USER}" == "postgres" ]; then
- echo "Choose a database user (but not 'postgres')"
- exit 4
-fi
-
-case $PRIVATE in
- /*) ABS_PRIVATE=$PRIVATE;;
- ./*|../*) ABS_PRIVATE=$PWD/$PRIVATE;;
- *) ABS_PRIVATE=$HERE/$PRIVATE;;
-esac
-
-[[ ! -f $ABS_PRIVATE/.trace.cega ]] && echo "You must run $HERE/cega.sh first" && exit 1
-
-#########################################################################
-# And....cue music
-#########################################################################
-
-rm_politely $ABS_PRIVATE/$INSTANCE
-mkdir -p $ABS_PRIVATE/$INSTANCE/{gpg,rsa,certs}
-
-echo -n "Generating private data for ${INSTANCE^^}"
-
-echomsg "\t* the GnuPG key"
-
-cat > $ABS_PRIVATE/$INSTANCE/gen_key < $ABS_PRIVATE/$INSTANCE/keys.conf < $ABS_PRIVATE/$INSTANCE/ega.conf < $ABS_PRIVATE/.env.d/$INSTANCE/db < $ABS_PRIVATE/.env.d/$INSTANCE/gpg < $ABS_PRIVATE/.trace.$INSTANCE < --batch --generate-key
-
-Make sure you have GnuPG version 2.2.0 (or higher)
-
-Use now `` in the `.env` file
-for the variable `GPG_HOME`. Use also `YourSECRETpassphrase` in the
-`.env.d/gpg` file for the variable `GPG_PASSPHRASE`.
-
-# Generating the RSA public and private keys
-
-
- openssl genpkey -algorithm RSA -out rsa.sec -pkeyopt rsa_keygen_bits:2048
- openssl rsa -pubout -in rsa.sec -out rsa.pubb
-
-Use then the location of `rsa.pub` and `rsa.sec` for the .env
-variables `RSA_PUB` and `RSA_SEC` respectively.
-
-
-# Generating the SSL certificates
-
- openssl req -x509 -newkey rsa:2048 -keyout ssl.key -nodes -out ssl.cert -sha256 -days 1000
-
-Use then the location of `ssl.cert` and `ssl.key` for the .env
-variables `SSL_CERT` and `SSL_KEY` respectively.
-
-# Generating some password hash for a user
-
- openssl passwd -1 -salt
-
-The `-1` switch makes it use MD5.
-
-# Generating some password hash for a rabbitMQ user
-
-Follow the instructions from: https://www.rabbitmq.com/passwords.html
diff --git a/docker/bootstrap/lib.sh b/docker/bootstrap/lib.sh
deleted file mode 100644
index a7269d15..00000000
--- a/docker/bootstrap/lib.sh
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env bash
-
-function echomsg {
- [[ -z "$VERBOSE" ]] && echo $@ && return 0
- if [[ "$VERBOSE" == 'yes' ]]; then
- echo -en "\n$@"
- else
- echo -n '.'
- fi
-}
-
-function task_complete {
- [[ -z "$VERBOSE" ]] && echo -e $@ && return 0
- if [[ $VERBOSE == 'yes' ]]; then
- echo -e "\n=> $1 \xF0\x9F\x91\x8D"
- else
- echo -e " \xF0\x9F\x91\x8D"
- fi
-}
-
-
-function backup {
- local target=$1
- if [[ -e $target ]]; then
- echomsg "Backing up $target"
- mv -f $target $target.$(date +"%Y-%m-%d_%H:%M:%S")
- fi
-}
-
-function rm_politely {
- local FOLDER=$1
-
- if [[ -d $FOLDER ]]; then
- if [[ $FORCE == 'yes' ]]; then
- rm -rf $FOLDER
- else
- # Asking
- echo "[Warning] The folder \"$FOLDER\" already exists. "
- while : ; do # while = In a subshell
- echo -n "[Warning] "
- echo -n -e "Proceed to re-create it? [y/N] "
- read -t 10 yn
- case $yn in
- y) rm -rf $FOLDER; break;;
- N) echo "Ok. Choose another private directory. Exiting"; exit 1;;
- *) echo "Eh?";;
- esac
- done
- fi
- fi
-}
-
-function generate_password {
- local size=${1:-16} # defaults to 16 characters
- p=$(python3.6 -c "import secrets,string;print(''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(${size})))")
- echo $p
-}
-
-function rabbitmq_hash {
- # 1) Generate a random 32 bit salt
- # 2) Concatenate that with the UTF-8 representation of the password
- # 3) Take the SHA-256 hash
- # 4) Concatenate the salt again
- # 5) Convert to base64 encoding
- local SALT=${2:-$(${OPENSSL:-openssl} rand -hex 4)}
- (
- printf $SALT | xxd -p -r
- ( printf $SALT | xxd -p -r; printf $1 ) | ${OPENSSL:-openssl} dgst -binary -sha256
- ) | base64
-}
-
-
-function join_by { local IFS="$1"; shift; echo -n "$*"; }
diff --git a/docker/bootstrap/populate.sh b/docker/bootstrap/populate.sh
deleted file mode 100755
index ad8e1972..00000000
--- a/docker/bootstrap/populate.sh
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/env bash
-
-SCRIPT=$(dirname ${BASH_SOURCE[0]})
-HERE=$PWD/${SCRIPT#./}
-
-source $HERE/lib.sh
-
-# Defaults:
-VERBOSE=no
-FORCE=yes
-PRIVATE=private
-SOURCES=$HERE/../../src
-ENTRYPOINTS=$HERE/../entrypoints
-
-function usage {
- echo "Usage: $0 [options]"
- echo -e "\nOptions are:"
- echo -e "\t--private_dir \tPath location of private data folder"
- echo -e "\t--sources \tPath Location of the src folder"
- echo -e "\t--entrypoints \tPath Location of the entrypoints folder"
- echo ""
- echo -e "\t--verbose, -v \tShow verbose output"
- echo -e "\t--polite, -p \tDo not force the re-creation of the subfolders. Ask instead"
- echo -e "\t--help, -h \tOutputs this message and exits"
- echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
- echo ""
-}
-
-# While there are arguments or '--' is reached
-while [[ $# -gt 0 ]]; do
- case "$1" in
- --help|-h) usage; exit 0;;
- --verbose|-v) VERBOSE=yes;;
- --polite|-p) FORCE=no;;
- --sources) SOURCES=$2; shift;;
- --entrypoints) ENTRYPOINTS=$2; shift;;
- --private_dir) PRIVATE=$2; shift;;
- --) shift; break;;
- *) echo "$0: error - unrecognized option $1" 1>&2; usage; exit 1;;
- esac
- shift
-done
-
-[[ $VERBOSE == 'yes' ]] && FORCE='no'
-
-echo -n "Populating files"
-
-case $PRIVATE in
- /*) ABS_PRIVATE=$PRIVATE;;
- ./*|../*) ABS_PRIVATE=$PWD/$PRIVATE;;
- *) ABS_PRIVATE=$HERE/$PRIVATE;;
-esac
-
-[[ -d $ABS_PRIVATE ]] || { echomsg "Private data folder $ABS_PRIVATE not found. Exiting" 1>&2; exit 1; }
-
-case $SOURCES in
- /*) ABS_SOURCES=$SOURCES;;
- ./*|../*) ABS_SOURCES=$PWD/$SOURCES;;
- *) ABS_SOURCES=$HERE/$SOURCES;;
-esac
-
-[[ -d $SOURCES ]] || { echomsg "Sources folder $ABS_SOURCES not found. Exiting" 1>&2; exit 1; }
-
-case $ENTRYPOINTS in
- /*) ABS_ENTRYPOINTS=$ENTRYPOINTS;;
- ./*|../*) ABS_ENTRYPOINTS=$PWD/$ENTRYPOINTS;;
- *) ABS_ENTRYPOINTS=$HERE/$ENTRYPOINTS;;
-esac
-
-[[ -d $ABS_ENTRYPOINTS ]] || { echomsg "Entrypoints folder $ABS_ENTRYPOINTS not found. Exiting" 1>&2; exit 1; }
-
-
-[[ $FORCE == 'yes' ]] || {
- backup $HERE/../.env
- backup $HERE/../.env.d
-}
-
-# Populate env-settings for docker compose
-cat > $HERE/../.env <> $HERE/../.env <#$HERE#g" $ABS_PRIVATE/.trace.cega > $ABS_PRIVATE/.trace.cega.tmp
- mv -f $ABS_PRIVATE/.trace.cega.tmp $ABS_PRIVATE/.trace.cega
- # Note: The -i did not work. Dunno why.
-fi
-
-task_complete "docker-compose configuration files populated"
diff --git a/docker/bootstrap/defaults/fin1 b/docker/bootstrap/settings/fin1
similarity index 67%
rename from docker/bootstrap/defaults/fin1
rename to docker/bootstrap/settings/fin1
index 8227162b..937fd3f7 100644
--- a/docker/bootstrap/defaults/fin1
+++ b/docker/bootstrap/settings/fin1
@@ -1,8 +1,11 @@
#!/usr/bin/env bash
set -e
-GPG=gpg
-OPENSSL=openssl
+DOCKER_INBOX_PORT=2223
+
+GREETINGS="Welcome to Local EGA Finland @ CSC"
+CEGA_MQ_PASSWORD=$(generate_password 16)
+CEGA_REST_PASSWORD=$(generate_password 16)
SSL_SUBJ="/C=FI/ST=Finland/L=Helsinki/O=CSC/OU=SysDevs/CN=LocalEGA/emailAddress=ega@csc.fi"
diff --git a/docker/bootstrap/defaults/swe1 b/docker/bootstrap/settings/swe1
similarity index 67%
rename from docker/bootstrap/defaults/swe1
rename to docker/bootstrap/settings/swe1
index 33de67c8..571e60f1 100644
--- a/docker/bootstrap/defaults/swe1
+++ b/docker/bootstrap/settings/swe1
@@ -1,8 +1,11 @@
#!/usr/bin/env bash
set -e
-GPG=gpg
-OPENSSL=openssl
+DOCKER_INBOX_PORT=2222
+
+GREETINGS="Welcome to Local EGA Sweden @ NBIS"
+CEGA_MQ_PASSWORD=$(generate_password 16)
+CEGA_REST_PASSWORD=$(generate_password 16)
SSL_SUBJ="/C=SE/ST=Sweden/L=Uppsala/O=NBIS/OU=SysDevs/CN=LocalEGA/emailAddress=ega@nbis.se"
diff --git a/docker/bootstrap/troubleshooting.md b/docker/bootstrap/troubleshooting.md
new file mode 100644
index 00000000..d02ae63d
--- /dev/null
+++ b/docker/bootstrap/troubleshooting.md
@@ -0,0 +1,17 @@
+# Troubleshooting
+
+* Use `-h` to see the possible options of each script, and `-v` for
+ verbose output.
+
+* If bootstrapping take more than a few seconds to run, it is usually
+ because your computer does not have enough entropy. You can use the
+ program `rng-tools` to solve this problem. E.g. on Debian/Ubuntu
+ system, install the software by
+
+ sudo apt-get install rng-tools
+
+ and then run
+
+ sudo rngd -r /dev/urandom
+
+
diff --git a/docker/bootstrap/yourself.md b/docker/bootstrap/yourself.md
deleted file mode 100644
index 947b0ebb..00000000
--- a/docker/bootstrap/yourself.md
+++ /dev/null
@@ -1,110 +0,0 @@
-## The environment variables
-
-It is necessary to create a `.env` file with the following variables:
-(mostly used to parameterize docker-compose)
-
-```
-COMPOSE_PROJECT_NAME=ega
-COMPOSE_FILE=ega.yml
-
-CODE= # path to folder where setup.py is
-CONF= # will be mounted in the containers as /etc/ega/conf.ini
-
-# settings regarding the encryption/decryption
-KEYS=
-SSL_CERT= # for the ingestion workers to communicate with the keys server
-SSL_KEY=
-RSA_SEC=
-RSA_PUB=
-GPG_HOME= # including pubring.kbx, trustdb.gpg, private-keys-v1.d and openpgp-revocs.d
-
-# Temporarily faking Central EGA
-CEGA_USERS= # containing one .yml file per user
-```
-
-You may get started with some extra instructions to create
-the [private data](bootstrap/README.md).
-
-For the database, we create `.env.d/db` containing:
-
-```
-POSTGRES_USER=
-POSTGRES_PASSWORD=
-```
-
-For the keyserver, we create `.env.d/gpg` containing:
-
-```
-GPG_PASSPHRASE=the-correct-passphrase
-```
-## The CONF file
-
-The file pointed by `CONF` should contain the values that reset those
-from [defaults.ini](../src/lega/conf/defaults.ini). For example:
-
-```
-[DEFAULT]
-# We want more output
-log = debug
-
-[ingestion]
-gpg_cmd = /usr/local/bin/gpg --homedir ~/.gnupg --decrypt %(file)s
-
-## Connecting to Central EGA
-[cega.broker]
-host = cega_mq
-username =
-password =
-vhost =
-heartbeat = 0
-
-[db]
-host = ega_db
-username =
-password =
-```
-
-All the other values will remain unchanged.
-Use `docker-compose exec ega-conf --list` in any container (but inbox).
-
-## The KEYS file
-
-The file pointed by `KEYS` should contain the information about the
-keys and will be located _only_ on the keyserver. For example:
-
-```
-[DEFAULT]
-active_master_key = 1
-
-[master.key.1]
-seckey = /etc/ega/rsa/sec.pem
-pubkey = /etc/ega/rsa/pub.pem
-passphrase =
-
-[master.key.2]
-seckey = /etc/ega/rsa/sec2.pem
-pubkey = /etc/ega/rsa/pub2.pem
-passphrase =
-```
-
-Docker will map the path from `RSA_PUB` in the `.env` file to
-`/etc/ega/rsa/pub.pem` in the keyserver container, for example.
-
-## A Central EGA user
-
-We fake the CentralEGA message broker and user database, with 2
-containers: `cega_mq` and `cega_users`.
-
-The `cega_users` is a very simple file-based server, that reads from
-the folder pointed by `CEGA_USERS`. The latter contains one file per user, of the following form:
-
-```
----
-password_hash: $1$xyz$sx8gPI05DJdJe4MJx5oXo0
-pubkey: ssh-rsa AAAAB3NzaC1yc...balbla...MiFw== some.comment@lega.sftp
-expiration: some interval
-```
-
-The file name `john.yml` is used for the user `john`. You must at
-least specify a `password_hash` or a `pubkey`. Other values can be
-empty or missing.
diff --git a/docker/ega.yml b/docker/ega.yml
index 4d8ac5af..922426a0 100644
--- a/docker/ega.yml
+++ b/docker/ega.yml
@@ -4,7 +4,6 @@ services:
# Local Message broker
mq_swe1:
- #env_file: .env.d/swe1/mq
hostname: ega_mq
ports:
- "15672:15672"
@@ -13,14 +12,14 @@ services:
# Postgres Database for Sweden
db_swe1:
- env_file: .env.d/swe1/db
+ env_file: private/swe1/db.env
hostname: ega_db_swe1
container_name: ega_db_swe1
image: nbisweden/ega-db
# Postgres Database for Finland
db_fin1:
- env_file: .env.d/fin1/db
+ env_file: private/fin1/db.env
hostname: ega_db_fin1
container_name: ega_db_fin1
image: nbisweden/ega-db
@@ -39,7 +38,7 @@ services:
volumes:
- ${CONF_swe1}:/etc/ega/conf.ini:ro
- ${CODE}:/root/ega
- - ${ENTRYPOINTS}/frontend.sh:/usr/local/bin/frontend.sh:ro
+ - ./entrypoints/frontend.sh:/usr/local/bin/frontend.sh:ro
command: frontend.sh
# SFTP inbox for Sweden
@@ -48,17 +47,17 @@ services:
depends_on:
- db_swe1
env_file:
- - .env.d/swe1/db
- - .env.d/swe1/cega
+ - private/swe1/db.env
+ - private/swe1/cega.env
ports:
- - "2222:22"
+ - "${DOCKER_INBOX_swe1_PORT}:22"
container_name: ega_inbox_swe1
image: nbisweden/ega-inbox
volumes:
- ${CODE}:/root/ega
- inbox_swe1:/ega/inbox
- ${CONF_swe1}:/etc/ega/conf.ini:ro
- - ${ENTRYPOINTS}/inbox.sh:/usr/local/bin/inbox.sh:ro
+ - ./entrypoints/inbox.sh:/usr/local/bin/inbox.sh:ro
command: ["inbox.sh","swe1"]
# SFTP inbox for Finland
@@ -67,17 +66,17 @@ services:
depends_on:
- db_fin1
env_file:
- - .env.d/fin1/db
- - .env.d/fin1/cega
+ - private/fin1/db.env
+ - private/fin1/cega.env
ports:
- - "2223:22"
+ - "${DOCKER_INBOX_fin1_PORT}:22"
container_name: ega_inbox_fin1
image: nbisweden/ega-inbox
volumes:
- ${CODE}:/root/ega
- inbox_fin1:/ega/inbox
- ${CONF_fin1}:/etc/ega/conf.ini:ro
- - ${ENTRYPOINTS}/inbox.sh:/usr/local/bin/inbox.sh:ro
+ - ./entrypoints/inbox.sh:/usr/local/bin/inbox.sh:ro
command: ["inbox.sh","fin1"]
# Vault
@@ -94,7 +93,7 @@ services:
- staging_swe1:/ega/staging
- vault_swe1:/ega/vault
- ${CONF_swe1}:/etc/ega/conf.ini:ro
- - ${ENTRYPOINTS}/vault.sh:/usr/local/bin/vault.sh:ro
+ - ./entrypoints/vault.sh:/usr/local/bin/vault.sh:ro
command: ["vault.sh","swe1"]
# Ingestion Workers
@@ -115,12 +114,12 @@ services:
- ${SSL_CERT_swe1}:/etc/ega/ssl.cert:ro
- ${GPG_HOME_swe1}/pubring.kbx:/root/.gnupg/pubring.kbx:ro
- ${GPG_HOME_swe1}/trustdb.gpg:/root/.gnupg/trustdb.gpg
- - ${ENTRYPOINTS}/ingest.sh:/usr/local/bin/ingest.sh:ro
+ - ./entrypoints/ingest.sh:/usr/local/bin/ingest.sh:ro
command: ["ingest.sh","swe1"]
# Key server
keys_swe1:
- env_file: .env.d/swe1/gpg
+ env_file: private/swe1/gpg.env
environment:
- GPG_TTY=/dev/console
hostname: ega_keys_swe1
@@ -142,7 +141,7 @@ services:
- ${GPG_HOME_swe1}/private-keys-v1.d:/root/.gnupg/private-keys-v1.d:ro
- ${RSA_SEC_swe1}:/etc/ega/rsa/sec.pem:ro
- ${RSA_PUB_swe1}:/etc/ega/rsa/pub.pem:ro
- - ${ENTRYPOINTS}/keys.sh:/usr/local/bin/keys.sh:ro
+ - ./entrypoints/keys.sh:/usr/local/bin/keys.sh:ro
command: keys.sh
# # Error Monitors
@@ -171,13 +170,14 @@ services:
- ${CEGA_MQ_DEFS}:/etc/rabbitmq/defs.json:ro
cega_users:
- env_file: .env.d/cega_instances
+ env_file: private/cega/env
image: nbisweden/ega-cega_users
container_name: cega_users
ports:
- "9100:80"
volumes:
- - ${CEGA_USERS}:/cega/users:rw
+ - ${CEGA_USERS}:/cega/users:rw
+
# Use the default driver for volume creation
volumes:
diff --git a/docker/images/Makefile b/docker/images/Makefile
index 01440b47..dd509af2 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -20,12 +20,16 @@ cega_users: common
$(EGA_IMAGES):
-docker pull $(TARGET)-$@:latest
- docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(TAG) --tag $(TARGET)-$@:latest $@
+ docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(TAG) $@
+ docker tag $(TARGET)-$@:$(TAG) $(TARGET)-$@:latest
push:
for image in $(EGA_IMAGES); do docker push $(TARGET)-$$image:latest; done
clean:
+ @docker images $(TARGET)-* -f "dangling=true" -q | uniq | while read n; do docker rmi $$n; done
+
+cleanall:
@docker images -f "dangling=true" -q | uniq | while read n; do docker rmi $$n; done
delete:
diff --git a/docker/images/worker/Dockerfile b/docker/images/worker/Dockerfile
index 77d360a4..7616ff3a 100644
--- a/docker/images/worker/Dockerfile
+++ b/docker/images/worker/Dockerfile
@@ -19,6 +19,8 @@ ARG NCURSES_VERSION=6.0
ARG PINENTRY_VERSION=1.0.0
ARG GNUPG_VERSION=2.2.2
+ARG GNUPG_SERVER=ftp://mirrors.dotsrc.org/gcrypt/
+
##############################################################
RUN mkdir -p /var/src/gnupg
WORKDIR /var/src/gnupg
@@ -27,32 +29,32 @@ WORKDIR /var/src/gnupg
RUN yum -y install zlib-devel bzip2-devel
# Install libgpg-error
-RUN curl -O ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz && \
- curl -O ftp://ftp.gnupg.org/gcrypt/libgpg-error/libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz.sig && \
+RUN curl -O ${GNUPG_SERVER}/libgpg-error/libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz && \
+ curl -O ${GNUPG_SERVER}/libgpg-error/libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz.sig && \
gpg --verify libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz.sig && tar -xzf libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz && \
pushd libgpg-error-${LIBGPG_ERROR_VERSION}/ && ./configure && make && make install && popd
# Install libgcrypt
-RUN curl -O ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-${LIBGCRYPT_VERSION}.tar.gz && \
- curl -O ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-${LIBGCRYPT_VERSION}.tar.gz.sig && \
+RUN curl -O ${GNUPG_SERVER}/libgcrypt/libgcrypt-${LIBGCRYPT_VERSION}.tar.gz && \
+ curl -O ${GNUPG_SERVER}/libgcrypt/libgcrypt-${LIBGCRYPT_VERSION}.tar.gz.sig && \
gpg --verify libgcrypt-${LIBGCRYPT_VERSION}.tar.gz.sig && tar -xzf libgcrypt-${LIBGCRYPT_VERSION}.tar.gz && \
pushd libgcrypt-${LIBGCRYPT_VERSION} && ./configure && make && make install && popd
# Install libassuan
-RUN curl -O ftp://ftp.gnupg.org/gcrypt/libassuan/libassuan-${LIBASSUAN_VERSION}.tar.bz2 && \
- curl -O ftp://ftp.gnupg.org/gcrypt/libassuan/libassuan-${LIBASSUAN_VERSION}.tar.bz2.sig && \
+RUN curl -O ${GNUPG_SERVER}/libassuan/libassuan-${LIBASSUAN_VERSION}.tar.bz2 && \
+ curl -O ${GNUPG_SERVER}/libassuan/libassuan-${LIBASSUAN_VERSION}.tar.bz2.sig && \
gpg --verify libassuan-${LIBASSUAN_VERSION}.tar.bz2.sig && tar -xjf libassuan-${LIBASSUAN_VERSION}.tar.bz2 && \
pushd libassuan-${LIBASSUAN_VERSION} && ./configure && make && make install && popd
# Install libksba
-RUN curl -O ftp://ftp.gnupg.org/gcrypt/libksba/libksba-${LIBKSBA_VERSION}.tar.bz2 && \
- curl -O ftp://ftp.gnupg.org/gcrypt/libksba/libksba-${LIBKSBA_VERSION}.tar.bz2.sig && \
+RUN curl -O ${GNUPG_SERVER}/libksba/libksba-${LIBKSBA_VERSION}.tar.bz2 && \
+ curl -O ${GNUPG_SERVER}/libksba/libksba-${LIBKSBA_VERSION}.tar.bz2.sig && \
gpg --verify libksba-${LIBKSBA_VERSION}.tar.bz2.sig && tar -xjf libksba-${LIBKSBA_VERSION}.tar.bz2 && \
pushd libksba-${LIBKSBA_VERSION} && ./configure && make && make install && popd
# Install libnpth
-RUN curl -O ftp://ftp.gnupg.org/gcrypt/npth/npth-${LIBNPTH_VERSION}.tar.bz2 && \
- curl -O ftp://ftp.gnupg.org/gcrypt/npth/npth-${LIBNPTH_VERSION}.tar.bz2.sig && \
+RUN curl -O ${GNUPG_SERVER}/npth/npth-${LIBNPTH_VERSION}.tar.bz2 && \
+ curl -O ${GNUPG_SERVER}/npth/npth-${LIBNPTH_VERSION}.tar.bz2.sig && \
gpg --verify npth-${LIBNPTH_VERSION}.tar.bz2.sig && tar -xjf npth-${LIBNPTH_VERSION}.tar.bz2 && \
pushd npth-${LIBNPTH_VERSION} && ./configure && make && make install && popd
@@ -63,15 +65,15 @@ RUN curl -O ftp://ftp.gnu.org/gnu/ncurses/ncurses-${NCURSES_VERSION}.tar.gz && \
pushd ncurses-${NCURSES_VERSION} && export CPPFLAGS="-P" && ./configure && make && make install && popd
# Install pinentry
-RUN curl -O ftp://ftp.gnupg.org/gcrypt/pinentry/pinentry-${PINENTRY_VERSION}.tar.bz2 && \
- curl -O ftp://ftp.gnupg.org/gcrypt/pinentry/pinentry-${PINENTRY_VERSION}.tar.bz2.sig && \
+RUN curl -O ${GNUPG_SERVER}/pinentry/pinentry-${PINENTRY_VERSION}.tar.bz2 && \
+ curl -O ${GNUPG_SERVER}/pinentry/pinentry-${PINENTRY_VERSION}.tar.bz2.sig && \
gpg --verify pinentry-${PINENTRY_VERSION}.tar.bz2.sig && tar -xjf pinentry-${PINENTRY_VERSION}.tar.bz2 && \
pushd pinentry-${PINENTRY_VERSION} && ./configure --enable-pinentry-curses --disable-pinentry-qt5 --enable-pinentry-tty && \
make && make install && popd
# Install
-RUN curl -O ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-${GNUPG_VERSION}.tar.bz2 && \
- curl -O ftp://ftp.gnupg.org/gcrypt/gnupg/gnupg-${GNUPG_VERSION}.tar.bz2.sig && \
+RUN curl -O ${GNUPG_SERVER}/gnupg/gnupg-${GNUPG_VERSION}.tar.bz2 && \
+ curl -O ${GNUPG_SERVER}/gnupg/gnupg-${GNUPG_VERSION}.tar.bz2.sig && \
gpg --verify gnupg-${GNUPG_VERSION}.tar.bz2.sig && tar -xjf gnupg-${GNUPG_VERSION}.tar.bz2 && \
pushd gnupg-${GNUPG_VERSION} && ./configure && make && make install && popd
From 9d363861cfc14d73785f9d1b5ce3d0f487b5b2c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Sun, 12 Nov 2017 23:45:31 +0100
Subject: [PATCH 091/528] RPMs for the GnuPG 2.2.2
---
docker/images/worker/Dockerfile | 93 ++----------------
docker/images/worker/rpmbuild/.gitignore | 3 +
docker/images/worker/rpmbuild/Makefile | 54 ++++++++++
.../rpmbuild/SOURCES/gnupg-2.2.2.tar.bz2.sig | Bin 0 -> 620 bytes
.../SOURCES/libassuan-2.4.3.tar.bz2.sig | Bin 0 -> 287 bytes
.../SOURCES/libgcrypt-1.8.1.tar.bz2.sig | Bin 0 -> 620 bytes
.../SOURCES/libgpg-error-1.27.tar.bz2.sig | Bin 0 -> 620 bytes
.../SOURCES/libksba-1.3.5.tar.bz2.sig | Bin 0 -> 287 bytes
.../rpmbuild/SOURCES/ncurses-6.0.tar.gz.sig | Bin 0 -> 72 bytes
.../rpmbuild/SOURCES/npth-1.5.tar.bz2.sig | Bin 0 -> 310 bytes
.../SOURCES/pinentry-1.0.0.tar.bz2.sig | Bin 0 -> 310 bytes
11 files changed, 63 insertions(+), 87 deletions(-)
create mode 100644 docker/images/worker/rpmbuild/.gitignore
create mode 100644 docker/images/worker/rpmbuild/Makefile
create mode 100644 docker/images/worker/rpmbuild/SOURCES/gnupg-2.2.2.tar.bz2.sig
create mode 100644 docker/images/worker/rpmbuild/SOURCES/libassuan-2.4.3.tar.bz2.sig
create mode 100644 docker/images/worker/rpmbuild/SOURCES/libgcrypt-1.8.1.tar.bz2.sig
create mode 100644 docker/images/worker/rpmbuild/SOURCES/libgpg-error-1.27.tar.bz2.sig
create mode 100644 docker/images/worker/rpmbuild/SOURCES/libksba-1.3.5.tar.bz2.sig
create mode 100644 docker/images/worker/rpmbuild/SOURCES/ncurses-6.0.tar.gz.sig
create mode 100644 docker/images/worker/rpmbuild/SOURCES/npth-1.5.tar.bz2.sig
create mode 100644 docker/images/worker/rpmbuild/SOURCES/pinentry-1.0.0.tar.bz2.sig
diff --git a/docker/images/worker/Dockerfile b/docker/images/worker/Dockerfile
index 7616ff3a..f14ac66a 100644
--- a/docker/images/worker/Dockerfile
+++ b/docker/images/worker/Dockerfile
@@ -1,94 +1,13 @@
FROM nbisweden/ega-common:latest
LABEL maintainer "Frédéric Haziza, NBIS"
-# Setup
-RUN gpg --list-keys && \
- gpg --keyserver eu.pool.sks-keyservers.net \
- --recv-keys 0x4F25E3B6 0xE0856959 0x33BD3F06 0x7EFD60D9 \
- 0xF7E48EDB
+RUN yum -y install vim-common zlib-devel bzip2-devel
+RUN mkdir -p /var/src/ega
-##############################################################
+COPY rpmbuild/RPMS/x86_64/*.rpm /var/src/ega/
-ARG LIBGPG_ERROR_VERSION=1.27
-ARG LIBGCRYPT_VERSION=1.8.1
-ARG LIBASSUAN_VERSION=2.4.3
-ARG LIBKSBA_VERSION=1.3.5
-ARG LIBNPTH_VERSION=1.5
-ARG NCURSES_VERSION=6.0
-ARG PINENTRY_VERSION=1.0.0
-ARG GNUPG_VERSION=2.2.2
-
-ARG GNUPG_SERVER=ftp://mirrors.dotsrc.org/gcrypt/
-
-##############################################################
-RUN mkdir -p /var/src/gnupg
-WORKDIR /var/src/gnupg
-
-# To get compression capabilities inside GnuPG
-RUN yum -y install zlib-devel bzip2-devel
-
-# Install libgpg-error
-RUN curl -O ${GNUPG_SERVER}/libgpg-error/libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz && \
- curl -O ${GNUPG_SERVER}/libgpg-error/libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz.sig && \
- gpg --verify libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz.sig && tar -xzf libgpg-error-${LIBGPG_ERROR_VERSION}.tar.gz && \
- pushd libgpg-error-${LIBGPG_ERROR_VERSION}/ && ./configure && make && make install && popd
-
-# Install libgcrypt
-RUN curl -O ${GNUPG_SERVER}/libgcrypt/libgcrypt-${LIBGCRYPT_VERSION}.tar.gz && \
- curl -O ${GNUPG_SERVER}/libgcrypt/libgcrypt-${LIBGCRYPT_VERSION}.tar.gz.sig && \
- gpg --verify libgcrypt-${LIBGCRYPT_VERSION}.tar.gz.sig && tar -xzf libgcrypt-${LIBGCRYPT_VERSION}.tar.gz && \
- pushd libgcrypt-${LIBGCRYPT_VERSION} && ./configure && make && make install && popd
-
-# Install libassuan
-RUN curl -O ${GNUPG_SERVER}/libassuan/libassuan-${LIBASSUAN_VERSION}.tar.bz2 && \
- curl -O ${GNUPG_SERVER}/libassuan/libassuan-${LIBASSUAN_VERSION}.tar.bz2.sig && \
- gpg --verify libassuan-${LIBASSUAN_VERSION}.tar.bz2.sig && tar -xjf libassuan-${LIBASSUAN_VERSION}.tar.bz2 && \
- pushd libassuan-${LIBASSUAN_VERSION} && ./configure && make && make install && popd
-
-# Install libksba
-RUN curl -O ${GNUPG_SERVER}/libksba/libksba-${LIBKSBA_VERSION}.tar.bz2 && \
- curl -O ${GNUPG_SERVER}/libksba/libksba-${LIBKSBA_VERSION}.tar.bz2.sig && \
- gpg --verify libksba-${LIBKSBA_VERSION}.tar.bz2.sig && tar -xjf libksba-${LIBKSBA_VERSION}.tar.bz2 && \
- pushd libksba-${LIBKSBA_VERSION} && ./configure && make && make install && popd
-
-# Install libnpth
-RUN curl -O ${GNUPG_SERVER}/npth/npth-${LIBNPTH_VERSION}.tar.bz2 && \
- curl -O ${GNUPG_SERVER}/npth/npth-${LIBNPTH_VERSION}.tar.bz2.sig && \
- gpg --verify npth-${LIBNPTH_VERSION}.tar.bz2.sig && tar -xjf npth-${LIBNPTH_VERSION}.tar.bz2 && \
- pushd npth-${LIBNPTH_VERSION} && ./configure && make && make install && popd
-
-# Install ncurses
-RUN curl -O ftp://ftp.gnu.org/gnu/ncurses/ncurses-${NCURSES_VERSION}.tar.gz && \
- curl -O ftp://ftp.gnu.org/gnu/ncurses/ncurses-${NCURSES_VERSION}.tar.gz.sig && \
- gpg --verify ncurses-${NCURSES_VERSION}.tar.gz.sig && tar -xzf ncurses-${NCURSES_VERSION}.tar.gz && \
- pushd ncurses-${NCURSES_VERSION} && export CPPFLAGS="-P" && ./configure && make && make install && popd
-
-# Install pinentry
-RUN curl -O ${GNUPG_SERVER}/pinentry/pinentry-${PINENTRY_VERSION}.tar.bz2 && \
- curl -O ${GNUPG_SERVER}/pinentry/pinentry-${PINENTRY_VERSION}.tar.bz2.sig && \
- gpg --verify pinentry-${PINENTRY_VERSION}.tar.bz2.sig && tar -xjf pinentry-${PINENTRY_VERSION}.tar.bz2 && \
- pushd pinentry-${PINENTRY_VERSION} && ./configure --enable-pinentry-curses --disable-pinentry-qt5 --enable-pinentry-tty && \
- make && make install && popd
-
-# Install
-RUN curl -O ${GNUPG_SERVER}/gnupg/gnupg-${GNUPG_VERSION}.tar.bz2 && \
- curl -O ${GNUPG_SERVER}/gnupg/gnupg-${GNUPG_VERSION}.tar.bz2.sig && \
- gpg --verify gnupg-${GNUPG_VERSION}.tar.bz2.sig && tar -xjf gnupg-${GNUPG_VERSION}.tar.bz2 && \
- pushd gnupg-${GNUPG_VERSION} && ./configure && make && make install && popd
-
-RUN echo "/usr/local/lib" > /etc/ld.so.conf.d/gpg2.conf && \
+RUN rpm -i /var/src/ega/*.rpm && \
+ rm -rf /var/src/ega && \
+ echo "/usr/local/lib64" > /etc/ld.so.conf.d/gpg2.conf && \
ldconfig -v
-
-##############################################################
-# Cleaning up
-RUN rm -rf /var/src/gnupg && \
- rm -rf /root/.gnupg && \
- mkdir -p /root/.gnupg && \
- chmod 700 /root/.gnupg && \
- mkdir -p /var/run/ega
-
-WORKDIR /
-
-# For the xxd utility
-RUN yum -y install vim-common
diff --git a/docker/images/worker/rpmbuild/.gitignore b/docker/images/worker/rpmbuild/.gitignore
new file mode 100644
index 00000000..c129d07b
--- /dev/null
+++ b/docker/images/worker/rpmbuild/.gitignore
@@ -0,0 +1,3 @@
+BUILD/
+BUILDROOT/
+SRPMS/
diff --git a/docker/images/worker/rpmbuild/Makefile b/docker/images/worker/rpmbuild/Makefile
new file mode 100644
index 00000000..de48276b
--- /dev/null
+++ b/docker/images/worker/rpmbuild/Makefile
@@ -0,0 +1,54 @@
+.PHONY: libgpg-error
+
+
+all: prepare libgpg-error libgcrypt libassuan libksba npth ncurses pinentry gnupg2
+
+BUILD_OPTS=--define '%debug_package %{nil}' --define '%_prefix /usr/local' --noclean --nocheck
+
+prepare:
+ yum -y install gcc curl bzip2 rpm-build zlib-devel bzip2-devel autoconf automake libtool gettext gettext-devel
+
+RPMS/x86_64/libgpg-error-1.27-1.el7.centos.x86_64.rpm: SPECS/libgpg-error.spec
+ @echo "Building ${<:SPECS/%.spec=%}"
+ rpmbuild $(BUILD_OPTS) -ba $<
+
+RPMS/x86_64/libgcrypt-1.8.1-1.el7.centos.x86_64.rpm: SPECS/libgcrypt.spec RPMS/x86_64/libgpg-error-1.27-1.el7.centos.x86_64.rpm
+ @echo "Building ${<:SPECS/%.spec=%}"
+ -rpm -i RPMS/x86_64/libgpg-error-1.27-1.el7.centos.x86_64.rpm
+ rpmbuild $(BUILD_OPTS) -ba $<
+
+RPMS/x86_64/libassuan-2.4.3-1.el7.centos.x86_64.rpm: SPECS/libassuan.spec
+ @echo "Building ${<:SPECS/%.spec=%}"
+ rpmbuild $(BUILD_OPTS) -ba $<
+
+RPMS/x86_64/libksba-1.3.5-1.el7.centos.x86_64.rpm: SPECS/libksba.spec
+ @echo "Building ${<:SPECS/%.spec=%}"
+ rpmbuild $(BUILD_OPTS) -ba $<
+
+RPMS/x86_64/npth-1.5-1.el7.centos.x86_64.rpm: SPECS/npth.spec
+ @echo "Building ${<:SPECS/%.spec=%}"
+ rpmbuild $(BUILD_OPTS) -ba $<
+
+RPMS/x86_64/ncurses-6.0-1.el7.centos.x86_64.rpm: SPECS/ncurses.spec
+ @echo "Building ${<:SPECS/%.spec=%}"
+ rpmbuild $(BUILD_OPTS) -ba $<
+
+RPMS/x86_64/pinentry-1.0.0-1.el7.centos.x86_64.rpm: SPECS/pinentry.spec ncurses libassuan
+ @echo "Building ${<:SPECS/%.spec=%}"
+ -rpm -i RPMS/x86_64/ncurses-6.0-1.el7.centos.x86_64.rpm RPMS/x86_64/libassuan-2.4.3-1.el7.centos.x86_64.rpm
+ rpmbuild $(BUILD_OPTS) -ba $<
+
+RPMS/x86_64/gnupg-2.2.2-1.el7.centos.x86_64.rpm: SPECS/gnupg2.spec npth libksba libgcrypt
+ @echo "Building ${<:SPECS/%.spec=%}"
+ -rpm -i RPMS/x86_64/npth-1.5-1.el7.centos.x86_64.rpm RPMS/x86_64/libksba-1.3.5-1.el7.centos.x86_64.rpm RPMS/x86_64/libgcrypt-1.8.1-1.el7.centos.x86_64.rpm
+ rpmbuild $(BUILD_OPTS) -ba $<
+
+
+libgpg-error: RPMS/x86_64/libgpg-error-1.27-1.el7.centos.x86_64.rpm
+libgcrypt: RPMS/x86_64/libgcrypt-1.8.1-1.el7.centos.x86_64.rpm
+libassuan: RPMS/x86_64/libassuan-2.4.3-1.el7.centos.x86_64.rpm
+libksba: RPMS/x86_64/libksba-1.3.5-1.el7.centos.x86_64.rpm
+npth: RPMS/x86_64/npth-1.5-1.el7.centos.x86_64.rpm
+ncurses: RPMS/x86_64/ncurses-6.0-1.el7.centos.x86_64.rpm
+pinentry: RPMS/x86_64/pinentry-1.0.0-1.el7.centos.x86_64.rpm
+gnupg2: RPMS/x86_64/gnupg-2.2.2-1.el7.centos.x86_64.rpm
diff --git a/docker/images/worker/rpmbuild/SOURCES/gnupg-2.2.2.tar.bz2.sig b/docker/images/worker/rpmbuild/SOURCES/gnupg-2.2.2.tar.bz2.sig
new file mode 100644
index 0000000000000000000000000000000000000000..9457c4d8587cd5fafdf21d3bd22638b0d042a296
GIT binary patch
literal 620
zcmV-y0+aoT0W$;u0SEvc79j-KX(1!T23_i24?49Zn>o@?CF8aQ0$Krq9smjn5G0#9
z(oZGhwgDLk0HZ#(S~EnbUpDlV!ZEIr9&KyX1nB)rX)PQE|TI4|L;#t+~V9Y!{z?#-%D(N^jJfkE3uDB;E66vJl8Q>_u20JOwxkT{^j}qkx(hC
z0%tEPqPNY#rnS8K@&b8Dh0aq=?YivkXYkAoqcth5;!RZ>2L2mRP4K0_i}Y~m5LO~
z3hc3lNQnV61ONdD038+~1OpzzQ*Kxdj-rOC@*r`riZi`G1_c6I0xa_Y3JDM(aj=Rr
zy*~zNm!Bz)|G>d$vbSbqaxvG1xoXhNd|lW9{w--EDf_I#jHlm3T>z6mKI
Gah>~~4I)JV
literal 0
HcmV?d00001
diff --git a/docker/images/worker/rpmbuild/SOURCES/libassuan-2.4.3.tar.bz2.sig b/docker/images/worker/rpmbuild/SOURCES/libassuan-2.4.3.tar.bz2.sig
new file mode 100644
index 0000000000000000000000000000000000000000..758d4b78f80ac523f9d10fc2c7e2ffe036147e7f
GIT binary patch
literal 287
zcmV+)0pR|L0UQJX0SEvF1p-%xNrM0i2@oWkInqxh`+#--4a#`=UUYf$%ntmav4hz-)dfGp$Q|kZl|)cjq5&
zi`t871>t--fp<_6#EyXi$A|JM5*CmYlF%~G3QoMA5r=E!hErt7+rUPZ(!~)3im>7N
z7;0`1z^esxC=HP^iUc<&ItjI300pzu49@y{9Ov;!V&=JXe;3H&;E_@3SRPO)cK$Vc
z;8m+n@EmNA35iHxzoT~60~x4URXwo;urDFAs6NXCC#m*|MXWtNm@A$&f1mbEkUb68
lNo@?CF8aQ0$HMUX#ffd5G0#9
z(oZGhwulM{0HV0mRIheb<6aMr-^r
z4C$RIB#I2;L0OZS`@wn3k1Um`i1cuLXkuw*
z;bD61f|W`ja3JhUUjV06Ui`z9I6$5bK*Ar&wRc%Z!O|nwtNb;{+Aj*VGJ4!KjPO@dkBzs*-^m
zRW+S=caKO;OrLEg?@Fjw@PzuSCJ^T42@IloEXWGQM3KO`J`e=BiLLyaXLN!ecoTti
ze#vZakcj~^1ONdD038+~1OpzzQ*Kxdj-rOC@*r`riZi`G1_c6Hr6yDW3JDM(aj=Rr
zy*~z;JqQ4pEsTZ=f%7aJYz@`5O~R4oV-K|jqXDJjib&$`uoE|RcVOZc$*}`C2y-$A
zFMMbm@^coau|K_Zs`TCbn%V~J%6Y&43T}pmpqgOi46U{>Pa3lR5AM@k7VTAS*t6b2B<;B9F(S&a6Bbu;X;^wNa2rXku$2EZzuZ@_<
GK#1J=&Ko}f
literal 0
HcmV?d00001
diff --git a/docker/images/worker/rpmbuild/SOURCES/libgpg-error-1.27.tar.bz2.sig b/docker/images/worker/rpmbuild/SOURCES/libgpg-error-1.27.tar.bz2.sig
new file mode 100644
index 0000000000000000000000000000000000000000..d9e89d3e62219fcabbd3daf8a7eaecf37597f295
GIT binary patch
literal 620
zcmV-y0+aoT0W$;u0SEvc79j-KX(1!T23_i24?49Zn>o@?CF8aQ0$8<%q5ujB5G0#9
z(oZGhwnOg+|5PM|`06i9Vy!z@lmprH$0Q+jDJXTcUj`e8nE@U!WvVkO0tfiD6X!3k
zN!GR*o%tMQxVzfixvL=*F3wT#G27m9r3rNfg@NDCn7g%Z_9Fwn?y!-2ZazS$M`y_G
zv<9mlDT;;eOQa@SK#tORKt(iPlbIjvF)XYRO&zTlFSA0z^NujPB`w_M^
z^%%)9e}V$b2&q>*$EjtT`oEBiq>mM=0MZl{55gwYdVgejKO3+kTvAIfjvV>XNRG{D
z*bga7!ifPh1ONdD038+~1OpzzQ*Kxdj-rOC@*r`riZi`G1_c6G<9)yY3JDM(aj=Rr
zy*~yQkO%;>pMNx+4@UZa7*LTlqD&M0+=BkB%7DREo
zy=TP2m~`Nf6DVb+<^aheH2%a4VCB)713{a##v6#n$fzHkC+YI#QOjx3I(W
zA*wu|*S{_~q=H5NK}UbYnmhqO&GDM(j3qO?C|HRTN|A&-{Ufq)jwZh@=#_aV{ns+}y(!`qMb0J7%+`gA
z1Cy6~ssm!O?)`O#v7okFRnjSV;~Y8m16J!E)L~U3q^lcFoHNR@go&T42!hivrFi?c
z7S-87L?$fZkvBRTD)S6nc-yz#fFf?oEaJ*g2vTFNr5pzfPW({GydJ4!v2WDos4#rf
zoxux_r}f|lJ4OOSAQ?+xD>lpos>1&w!+@nD}kQYw#Ew
e%XPLG5&)lMNk{q0c_}>do4j6D*Ur1oi9*fpiy&+O
literal 0
HcmV?d00001
diff --git a/docker/images/worker/rpmbuild/SOURCES/npth-1.5.tar.bz2.sig b/docker/images/worker/rpmbuild/SOURCES/npth-1.5.tar.bz2.sig
new file mode 100644
index 0000000000000000000000000000000000000000..a4cc351d4a3ca287aded4ddbfd4728baa598cb38
GIT binary patch
literal 310
zcmV-60m=S}0W$;u0SEvc79j-KX(1!T23_i24?49Zn>o@?CF8aQ0$DL7P5=rC5G0#9
z(oZGhwkNg-0E0?o_JRs-KdpLId|j7nw`A6``8VZ>JbA8X|4E)Y_yHHrY
zo*Z9j_j=GF)Y$oGHtrnNwlQYI<_7i5u-8|AB>Do3A7u596!oh;hi4^c4UD~@`(kI_
zeu(fF<%c?$0Q0d*ulLa^ah#&dDu%`8%y||&ucmz_E*a?WN3hoDD{I;mc(WkF0cMA;
zI@n55UA@s`t~2+~)wwc}FJaK*p14<=&hy$b*1-B#YjfDbX%3oLS+sg!W)}Y3f=0FDy!~qp}(<7jt
IZf+yso{qqj2LJ#7
literal 0
HcmV?d00001
diff --git a/docker/images/worker/rpmbuild/SOURCES/pinentry-1.0.0.tar.bz2.sig b/docker/images/worker/rpmbuild/SOURCES/pinentry-1.0.0.tar.bz2.sig
new file mode 100644
index 0000000000000000000000000000000000000000..107c9f16b851e5a25795342d7c56766be5af58b0
GIT binary patch
literal 310
zcmV-60m=S}0W$;u0SEvc79j-KX(1!T23_i24?49Zn>o@?CF8aQ0$4Nr-2e&+5G0#9
z(oZGhww3D#|77`=M_1RdKgJYiiJZr%L}Rw1EUJiMaB6uezCYx>T4yiR5TI88zVKMt&KVtQA)w?9h(gK5!_gt;;JTNGt*R`w$m8BKjcELW57wyvPs5EJF&D~bi-X9}Wl~Yogl~Nm1K}Ul}Fl2A~
I^pU52@d_r7F#rGn
literal 0
HcmV?d00001
From 04ec2c2e9064c7d6b02f49c55c5f980be5b61d38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 13 Nov 2017 01:12:57 +0100
Subject: [PATCH 092/528] Fixing stupid mistakes
---
docker/Makefile | 10 +++++++---
docker/bootstrap/boot.sh | 2 +-
docker/bootstrap/settings/fin1 | 2 +-
docker/bootstrap/settings/swe1 | 2 +-
docker/entrypoints/inbox.sh | 2 +-
docker/entrypoints/keys.sh | 11 ++++++++---
6 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/docker/Makefile b/docker/Makefile
index b52f0d92..7b34e7c6 100644
--- a/docker/Makefile
+++ b/docker/Makefile
@@ -8,12 +8,16 @@ all: up
bootstrap: .env private
-up: .env private
+clean:
+ rm -rf .env private
+
+up: bootstrap
@docker-compose up -d
+ps:
+ @docker-compose ps
+
down: #.env
@docker-compose down -v
-clean:
- rm -rf .env private
diff --git a/docker/bootstrap/boot.sh b/docker/bootstrap/boot.sh
index 1b622406..fb460fff 100755
--- a/docker/bootstrap/boot.sh
+++ b/docker/bootstrap/boot.sh
@@ -11,7 +11,7 @@ SETTINGS=${HERE}/settings
VERBOSE=no
FORCE=yes
OPENSSL=openssl
-GPG=gpg
+GPG=gpg2
GPG_CONF=gpgconf
function usage {
diff --git a/docker/bootstrap/settings/fin1 b/docker/bootstrap/settings/fin1
index 937fd3f7..b16784bb 100644
--- a/docker/bootstrap/settings/fin1
+++ b/docker/bootstrap/settings/fin1
@@ -3,7 +3,7 @@ set -e
DOCKER_INBOX_PORT=2223
-GREETINGS="Welcome to Local EGA Finland @ CSC"
+LEGA_GREETINGS="Welcome to Local EGA Finland @ CSC"
CEGA_MQ_PASSWORD=$(generate_password 16)
CEGA_REST_PASSWORD=$(generate_password 16)
diff --git a/docker/bootstrap/settings/swe1 b/docker/bootstrap/settings/swe1
index 571e60f1..870926a1 100644
--- a/docker/bootstrap/settings/swe1
+++ b/docker/bootstrap/settings/swe1
@@ -3,7 +3,7 @@ set -e
DOCKER_INBOX_PORT=2222
-GREETINGS="Welcome to Local EGA Sweden @ NBIS"
+LEGA_GREETINGS="Welcome to Local EGA Sweden @ NBIS"
CEGA_MQ_PASSWORD=$(generate_password 16)
CEGA_REST_PASSWORD=$(generate_password 16)
diff --git a/docker/entrypoints/inbox.sh b/docker/entrypoints/inbox.sh
index dbf17363..8d73c0c0 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/entrypoints/inbox.sh
@@ -58,7 +58,7 @@ chmod 750 /usr/local/bin/ega_ssh_keys.sh
chgrp ega /usr/local/bin/ega_ssh_keys.sh
# Greetings per site
-[[ -z "${LEGA_INSTANCE_GREETING}" ]] || echo ${LEGA_INSTANCE_GREETING} > /ega/banner
+[[ -z "${LEGA_GREETINGS}" ]] || echo ${LEGA_GREETING} > /ega/banner
echo "Starting the SFTP server"
exec /usr/sbin/sshd -D -e
diff --git a/docker/entrypoints/keys.sh b/docker/entrypoints/keys.sh
index 1229ac60..bba2933c 100755
--- a/docker/entrypoints/keys.sh
+++ b/docker/entrypoints/keys.sh
@@ -5,6 +5,10 @@ set -e
cp -r /root/ega /root/run
pip3.6 install /root/run
+GPG=/usr/local/bin/gpg2
+GPG_AGENT=/usr/local/bin/gpg-agent
+GPG_PRESET=/usr/local/libexec/gpg-preset-passphrase
+
chmod 700 /root/.gnupg
pkill gpg-agent || true
#/usr/local/bin/gpgconf --kill gpg-agent || true
@@ -24,13 +28,14 @@ disable-scdaemon
#disable-check-own-socket
EOF
+
# Start the GPG Agent in /root/.gnupg
-/usr/local/bin/gpg-agent --daemon
+${GPG_AGENT} --daemon
# This should create /run/ega/S.gpg-agent{,.extra,.ssh}
#while gpg-connect-agent /bye; do sleep 2; done
-KEYGRIP=$(/usr/local/bin/gpg -k --with-keygrip ega@nbis.se | awk '/Keygrip/{print $3;exit;}')
-/usr/local/libexec/gpg-preset-passphrase --preset -P $GPG_PASSPHRASE $KEYGRIP
+KEYGRIP=$(${GPG} -k --with-keygrip ega@nbis.se | awk '/Keygrip/{print $3;exit;}')
+${GPG_PRESET} --preset -P $GPG_PASSPHRASE $KEYGRIP
unset GPG_PASSPHRASE
echo "Starting the gpg-agent proxy"
From e090df9c5d18612ebb6395d1540f27e67f115f1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 13 Nov 2017 01:15:26 +0100
Subject: [PATCH 093/528] Cleaning the rpmbuild Makefile
---
docker/images/worker/rpmbuild/Makefile | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/docker/images/worker/rpmbuild/Makefile b/docker/images/worker/rpmbuild/Makefile
index de48276b..e80808a8 100644
--- a/docker/images/worker/rpmbuild/Makefile
+++ b/docker/images/worker/rpmbuild/Makefile
@@ -1,10 +1,7 @@
-.PHONY: libgpg-error
-
+BUILD_OPTS=--define '%debug_package %{nil}' --define '%_prefix /usr/local' --noclean --nocheck
all: prepare libgpg-error libgcrypt libassuan libksba npth ncurses pinentry gnupg2
-BUILD_OPTS=--define '%debug_package %{nil}' --define '%_prefix /usr/local' --noclean --nocheck
-
prepare:
yum -y install gcc curl bzip2 rpm-build zlib-devel bzip2-devel autoconf automake libtool gettext gettext-devel
From 7ac2fa351f3a7cc07ca73bbb10920b0852142030 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 13 Nov 2017 01:31:10 +0100
Subject: [PATCH 094/528] .gitignore was hidding the lib dir in bootstrap
---
docker/.gitignore | 5 +-
docker/bootstrap/.gitignore | 3 -
docker/bootstrap/lib/cega_mq.sh | 102 ++++++++++++++++
docker/bootstrap/lib/cega_users.sh | 70 +++++++++++
docker/bootstrap/lib/defs.sh | 58 +++++++++
docker/bootstrap/lib/instance.sh | 184 +++++++++++++++++++++++++++++
6 files changed, 417 insertions(+), 5 deletions(-)
delete mode 100644 docker/bootstrap/.gitignore
create mode 100644 docker/bootstrap/lib/cega_mq.sh
create mode 100644 docker/bootstrap/lib/cega_users.sh
create mode 100644 docker/bootstrap/lib/defs.sh
create mode 100755 docker/bootstrap/lib/instance.sh
diff --git a/docker/.gitignore b/docker/.gitignore
index 70cfdf35..b9761ef0 100644
--- a/docker/.gitignore
+++ b/docker/.gitignore
@@ -1,4 +1,5 @@
.env
-.env.d/
.env.201*
-.env.d.201*
+private*
+.err
+!bootstrap/lib
diff --git a/docker/bootstrap/.gitignore b/docker/bootstrap/.gitignore
deleted file mode 100644
index 32afa4f9..00000000
--- a/docker/bootstrap/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-private
-.err
-.log
diff --git a/docker/bootstrap/lib/cega_mq.sh b/docker/bootstrap/lib/cega_mq.sh
new file mode 100644
index 00000000..b572db11
--- /dev/null
+++ b/docker/bootstrap/lib/cega_mq.sh
@@ -0,0 +1,102 @@
+#!/usr/bin/env bash
+set -e
+
+echomsg "Generating passwords for the Message Broker"
+
+mkdir -p ${PRIVATE}/cega/mq
+
+function rabbitmq_hash {
+ # 1) Generate a random 32 bit salt
+ # 2) Concatenate that with the UTF-8 representation of the password
+ # 3) Take the SHA-256 hash
+ # 4) Concatenate the salt again
+ # 5) Convert to base64 encoding
+ local SALT=${2:-$(${OPENSSL:-openssl} rand -hex 4)}
+ {
+ printf ${SALT} | xxd -p -r
+ ( printf ${SALT} | xxd -p -r; printf $1 ) | ${OPENSSL:-openssl} dgst -binary -sha256
+ } | base64
+}
+
+
+function join_by { local IFS="$1"; shift; echo -n "$*"; }
+
+function output_password_hashes {
+ declare -a tmp
+ for INSTANCE in ${INSTANCES}
+ do
+ CEGA_MQ_PASSWORD=$(awk -F= '/CEGA_MQ_PASSWORD/{print $2}' ${PRIVATE}/${INSTANCE}/.trace)
+ CEGA_MQ_HASH=$(rabbitmq_hash $CEGA_MQ_PASSWORD)
+ tmp+=("{\"name\":\"cega_${INSTANCE}\",\"password_hash\":\"${CEGA_MQ_HASH}\",\"hashing_algorithm\":\"rabbit_password_hashing_sha256\",\"tags\":\"administrator\"}")
+ done
+ join_by ",\n" "${tmp[@]}"
+}
+
+function output_vhosts {
+ declare -a tmp
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"name\":\"${INSTANCE}\"}")
+ done
+ join_by "," "${tmp[@]}"
+}
+
+function output_permissions {
+ declare -a tmp
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"user\":\"cega_${INSTANCE}\", \"vhost\":\"${INSTANCE}\", \"configure\":\".*\", \"write\":\".*\", \"read\":\".*\"}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+function output_queues {
+ declare -a tmp
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"name\":\"${INSTANCE}.v1.commands.file\", \"vhost\":\"${INSTANCE}\", \"durable\":true, \"auto_delete\":false, \"arguments\":{}}")
+ tmp+=("{\"name\":\"${INSTANCE}.v1.commands.completed\", \"vhost\":\"${INSTANCE}\", \"durable\":true, \"auto_delete\":false, \"arguments\":{}}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+function output_exchanges {
+ declare -a tmp
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"name\":\"localega.v1\", \"vhost\":\"${INSTANCE}\", \"type\":\"topic\", \"durable\":true, \"auto_delete\":false, \"internal\":false, \"arguments\":{}}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+
+function output_bindings {
+ declare -a tmp
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"source\":\"localega.v1\",\"vhost\":\"${INSTANCE}\",\"destination_type\":\"queue\",\"arguments\":{},\"destination\":\"${INSTANCE}.v1.commands.file\",\"routing_key\":\"${INSTANCE}.file\"}")
+ tmp+=("{\"source\":\"localega.v1\",\"vhost\":\"${INSTANCE}\",\"destination_type\":\"queue\",\"arguments\":{},\"destination\":\"${INSTANCE}.v1.commands.completed\",\"routing_key\":\"${INSTANCE}.completed\"}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+cat > ${PRIVATE}/cega/mq/defs.json <> ${DOT_ENV} < ${PRIVATE}/cega/users/john.yml < ${PRIVATE}/cega/users/jane.yml < ${PRIVATE}/cega/users/taylor.yml <> ${PRIVATE}/cega/.trace < $1 \xF0\x9F\x91\x8D"
+ else
+ echo -e " \xF0\x9F\x91\x8D"
+ fi
+}
+
+
+function backup {
+ local target=$1
+ if [[ -e $target ]] && [[ $FORCE != 'yes' ]]; then
+ echomsg "Backing up $target"
+ mv -f $target $target.$(date +"%Y-%m-%d_%H:%M:%S")
+ fi
+}
+
+function rm_politely {
+ local FOLDER=$1
+
+ if [[ -d $FOLDER ]]; then
+ if [[ $FORCE == 'yes' ]]; then
+ rm -rf $FOLDER
+ else
+ # Asking
+ echo "[Warning] The folder \"$FOLDER\" already exists. "
+ while : ; do # while = In a subshell
+ echo -n "[Warning] "
+ echo -n -e "Proceed to re-create it? [y/N] "
+ read -t 10 yn
+ case $yn in
+ y) rm -rf $FOLDER; break;;
+ N) echo "Ok. Choose another private directory. Exiting"; exit 1;;
+ *) echo "Eh?";;
+ esac
+ done
+ fi
+ fi
+}
+
+function generate_password {
+ local size=${1:-16} # defaults to 16 characters
+ p=$(python3.6 -c "import secrets,string;print(''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(${size})))")
+ echo $p
+}
+
diff --git a/docker/bootstrap/lib/instance.sh b/docker/bootstrap/lib/instance.sh
new file mode 100755
index 00000000..c08f5f78
--- /dev/null
+++ b/docker/bootstrap/lib/instance.sh
@@ -0,0 +1,184 @@
+#!/usr/bin/env bash
+
+echomsg "Generating private data for ${INSTANCE} [Default in ${SETTINGS}/${INSTANCE}]"
+
+########################################################
+# Loading the instance's settings
+
+if [[ -f ${SETTINGS}/${INSTANCE} ]]; then
+ source ${SETTINGS}/${INSTANCE}
+else
+ echo "No settings found for ${INSTANCE}"
+ exit 1
+fi
+
+[[ -x $(readlink ${GPG}) ]] && echo "${GPG} is not executable. Adjust the setting with --gpg" && exit 2
+[[ -x $(readlink ${OPENSSL}) ]] && echo "${OPENSSL} is not executable. Adjust the setting with --openssl" && exit 3
+
+if [ -z "${DB_USER}" -o "${DB_USER}" == "postgres" ]; then
+ echo "Choose a database user (but not 'postgres')"
+ exit 4
+fi
+
+#########################################################################
+# And....cue music
+#########################################################################
+
+mkdir -p $PRIVATE/${INSTANCE}/{gpg,rsa,certs}
+chmod 700 $PRIVATE/${INSTANCE}/{gpg,rsa,certs}
+
+echomsg "\t* the GnuPG key"
+
+cat > ${PRIVATE}/${INSTANCE}/gen_key < ${PRIVATE}/${INSTANCE}/keys.conf < ${PRIVATE}/${INSTANCE}/ega.conf < ${PRIVATE}/${INSTANCE}/db.env < ${PRIVATE}/${INSTANCE}/gpg.env <> ${PRIVATE}/cega/env < ${PRIVATE}/${INSTANCE}/cega.env <> ${DOT_ENV} <> ${PRIVATE}/${INSTANCE}/.trace <
Date: Mon, 13 Nov 2017 01:37:51 +0100
Subject: [PATCH 095/528] Removing :latest before pulling
---
docker/images/Makefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/docker/images/Makefile b/docker/images/Makefile
index dd509af2..d0577b65 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -19,7 +19,8 @@ worker: common
cega_users: common
$(EGA_IMAGES):
- -docker pull $(TARGET)-$@:latest
+ docker rmi $(TARGET)-$@:latest
+ docker pull $(TARGET)-$@:latest
docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(TAG) $@
docker tag $(TARGET)-$@:$(TAG) $(TARGET)-$@:latest
From e78f6d630c4ce51a8921b2ec93d0ec644b3ed3fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 13 Nov 2017 01:53:45 +0100
Subject: [PATCH 096/528] Updating the tests with new location of private
folder
---
tests/src/test/java/se/nbis/lega/cucumber/Utils.java | 2 +-
.../se/nbis/lega/cucumber/steps/Authentication.java | 4 ++--
.../java/se/nbis/lega/cucumber/steps/Uploading.java | 10 +++++++---
3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index baafab90..14af417e 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -62,7 +62,7 @@ public String executeWithinContainer(Container container, String... command) thr
* @throws IOException In case it's not possible to read trace file.
*/
public String readTraceProperty(String fileName, String property) throws IOException {
- File trace = new File(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/" + fileName);
+ File trace = new File(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/private/" + fileName);
return FileUtils.readLines(trace, Charset.defaultCharset()).
stream().
filter(l -> l.startsWith(property)).
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 3549c673..7e71253d 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -18,7 +18,7 @@ public Authentication(Context context) {
Given("^I am a user \"([^\"]*)\"$", context::setUser);
Given("^I have a private key$",
- () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", context.getUser()))));
+ () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/private/cega/users/%s.sec", context.getUser()))));
When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
try {
@@ -43,4 +43,4 @@ public Authentication(Context context) {
});
}
-}
\ No newline at end of file
+}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index cd10200a..491b1206 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -33,8 +33,12 @@ public Uploading(Context context) {
createContainerCmd("nbisweden/ega-worker").
withVolumes(dataVolume, gpgVolume).
withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
- new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/swe1/gpg", gpgVolume, AccessMode.ro)).
- withCmd(utils.readTraceProperty(".trace.swe1", "GPG exec"), "-r", utils.readTraceProperty(".trace.swe1", "GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
+ new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/private/swe1/gpg", gpgVolume, AccessMode.ro)).
+ withCmd("gpg2" //utils.readTraceProperty("swe1/.trace", "GPG exec"),
+ "-r",
+ utils.readTraceProperty("swe1/.trace", "GPG_EMAIL"),
+ "-e",
+ "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
exec();
dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
@@ -68,4 +72,4 @@ public Uploading(Context context) {
});
}
-}
\ No newline at end of file
+}
From e8c0a7d357e6984d033a62c2a28605e4879e06d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 13 Nov 2017 01:57:51 +0100
Subject: [PATCH 097/528] Ohh...just a f***ing comma
---
tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index 491b1206..ede86b40 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -34,7 +34,7 @@ public Uploading(Context context) {
withVolumes(dataVolume, gpgVolume).
withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/private/swe1/gpg", gpgVolume, AccessMode.ro)).
- withCmd("gpg2" //utils.readTraceProperty("swe1/.trace", "GPG exec"),
+ withCmd("gpg2", //utils.readTraceProperty("swe1/.trace", "GPG exec"),
"-r",
utils.readTraceProperty("swe1/.trace", "GPG_EMAIL"),
"-e",
From 26999aa0fef8bd259674c04680e960e89ff248a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 13 Nov 2017 02:05:37 +0100
Subject: [PATCH 098/528] fetch MQ passwords from private//.trace
---
.../test/java/se/nbis/lega/cucumber/steps/Ingestion.java | 6 +++---
.../src/test/resources/cucumber/features/ingestion.feature | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
index 5659809c..f5943459 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -16,10 +16,10 @@ public class Ingestion implements En {
public Ingestion(Context context) {
Utils utils = context.getUtils();
- Given("^I have CEGA username and password$", () -> {
+ Given("^I have CEGA MQ username and password$", () -> {
try {
context.setCegaMQUser("cega_swe1");
- context.setCegaMQPassword(utils.readTraceProperty(".trace.cega", "CEGA_MQ_swe1_PASSWORD"));
+ context.setCegaMQPassword(utils.readTraceProperty("swe1/.trace", "CEGA_MQ_PASSWORD"));
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -61,4 +61,4 @@ public Ingestion(Context context) {
});
}
-}
\ No newline at end of file
+}
diff --git a/tests/src/test/resources/cucumber/features/ingestion.feature b/tests/src/test/resources/cucumber/features/ingestion.feature
index d93b426e..cd64dc43 100644
--- a/tests/src/test/resources/cucumber/features/ingestion.feature
+++ b/tests/src/test/resources/cucumber/features/ingestion.feature
@@ -7,6 +7,6 @@ Feature: Ingestion
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
And I upload encrypted file to the LocalEGA inbox via SFTP
- And I have CEGA username and password
+ And I have CEGA MQ username and password
When I ingest file from the LocalEGA inbox
- Then the file is ingested successfully
\ No newline at end of file
+ Then the file is ingested successfully
From 61daf95e3e2d19ce8a8f0ade8bd854322d63c821 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 13 Nov 2017 02:08:30 +0100
Subject: [PATCH 099/528] Ignore failure if :latest does not exist
---
docker/images/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/images/Makefile b/docker/images/Makefile
index d0577b65..ec7563bc 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -19,7 +19,7 @@ worker: common
cega_users: common
$(EGA_IMAGES):
- docker rmi $(TARGET)-$@:latest
+ -docker rmi $(TARGET)-$@:latest
docker pull $(TARGET)-$@:latest
docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(TAG) $@
docker tag $(TARGET)-$@:$(TAG) $(TARGET)-$@:latest
From f7728d832791fe4ab263eb742b1669d42eb21f58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 13 Nov 2017 02:10:47 +0100
Subject: [PATCH 100/528] Allez...hop....one more!
---
tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
index f5943459..dc0f6ebe 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -50,7 +50,7 @@ public Ingestion(Context context) {
Thread.sleep(1000);
String query = String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName());
String output = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-db", "/ega_db_swe1"),
- "psql", "-U", utils.readTraceProperty(".trace.swe1", "DB_USER"), "-d", "lega", "-c", query);
+ "psql", "-U", utils.readTraceProperty("swe1/.trace", "DB_USER"), "-d", "lega", "-c", query);
String vaultFileName = output.split(System.getProperty("line.separator"))[2];
String cat = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-common", "/ega_vault_swe1"), "cat", vaultFileName.trim());
Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
From 3c3b4be435044339806e9d52c0bb61a4de73aef8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Mon, 13 Nov 2017 02:17:05 +0100
Subject: [PATCH 101/528] Well..no...not ignoring the :latest not found
---
docker/images/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/images/Makefile b/docker/images/Makefile
index ec7563bc..d0577b65 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -19,7 +19,7 @@ worker: common
cega_users: common
$(EGA_IMAGES):
- -docker rmi $(TARGET)-$@:latest
+ docker rmi $(TARGET)-$@:latest
docker pull $(TARGET)-$@:latest
docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(TAG) $@
docker tag $(TARGET)-$@:$(TAG) $(TARGET)-$@:latest
From 0849855254c75ca1bf85e99f491973c427291ac0 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 14:30:23 +0100
Subject: [PATCH 102/528] Refactor tests, add authentication tests.
---
.../java/se/nbis/lega/cucumber/Context.java | 10 +-
.../java/se/nbis/lega/cucumber/Tests.java | 8 --
.../java/se/nbis/lega/cucumber/Utils.java | 44 +++++++-
.../lega/cucumber/hooks/BeforeAfterHooks.java | 42 +++++++
.../lega/cucumber/steps/Authentication.java | 103 +++++++++++++++---
.../nbis/lega/cucumber/steps/Ingestion.java | 23 ++--
.../nbis/lega/cucumber/steps/Uploading.java | 33 +++---
.../cucumber/features/authentication.feature | 34 +++++-
.../cucumber/features/ingestion.feature | 5 +-
.../cucumber/features/uploading.feature | 5 +-
10 files changed, 240 insertions(+), 67 deletions(-)
create mode 100644 tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Context.java b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
index afcdb288..d7819dfd 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Context.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
@@ -2,11 +2,8 @@
import lombok.Data;
import net.schmizz.sshj.sftp.SFTPClient;
-import org.apache.commons.io.FileUtils;
import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
@Data
public class Context {
@@ -22,11 +19,6 @@ public class Context {
private File rawFile;
private File encryptedFile;
- public Context() throws IOException {
- dataFolder = new File("data");
- dataFolder.mkdir();
- rawFile = File.createTempFile("data", ".raw", dataFolder);
- FileUtils.writeStringToFile(rawFile, "hello", Charset.defaultCharset());
- }
+ private boolean authenticationFailed;
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Tests.java b/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
index 1c18e386..e442eb01 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Tests.java
@@ -15,12 +15,4 @@
features = "src/test/resources/cucumber/features"
)
public class Tests {
-
- public static final String DATA_FOLDER_PATH = "data";
-
- @AfterClass
- public static void teardown() throws IOException {
- FileUtils.deleteDirectory(new File(DATA_FOLDER_PATH));
- }
-
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index 14af417e..f8e9f956 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -1,10 +1,15 @@
package se.nbis.lega.cucumber;
import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.model.AccessMode;
+import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Container;
+import com.github.dockerjava.api.model.Volume;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.command.ExecStartResultCallback;
+import com.github.dockerjava.core.command.WaitContainerResultCallback;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ArrayUtils;
@@ -54,6 +59,43 @@ public String executeWithinContainer(Container container, String... command) thr
return new String(outputStream.toByteArray());
}
+ /**
+ * Executes PSQL query.
+ *
+ * @param query Query to execute.
+ * @return Query output.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public String executeDBQuery(String query) throws IOException, InterruptedException {
+ return executeWithinContainer(findContainer("nbis/ega:db", "ega_db"), "psql", "-U", readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
+ }
+
+ /**
+ * Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
+ *
+ * @param from Folder to mount from.
+ * @param to Folder to mount to.
+ * @param command Command to execute.
+ * @throws InterruptedException In case the command execution is interrupted.
+ */
+ public void spawnWorkerAndExecute(String from, String to, String... command) throws InterruptedException {
+ Volume dataVolume = new Volume(to);
+ Volume gpgVolume = new Volume("/root/.gnupg");
+ CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerCmd("nbis/ega:worker").
+ withVolumes(dataVolume, gpgVolume).
+ withBinds(new Bind(from, dataVolume),
+ new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
+ withCmd(command).
+ exec();
+ dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
+ WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
+ dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback);
+ resultCallback.awaitCompletion();
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).exec();
+ }
+
/**
* Reads property from the trace file.
*
@@ -81,7 +123,7 @@ public Container findContainer(String imageName, String containerName) {
return dockerClient.listContainersCmd().exec().
stream().
filter(c -> c.getImage().equals(imageName)).
- filter(c -> ArrayUtils.contains(c.getNames(), containerName)).
+ filter(c -> ArrayUtils.contains(c.getNames(), "/" + containerName)).
findAny().
orElse(null);
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
new file mode 100644
index 00000000..30c3fb9d
--- /dev/null
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -0,0 +1,42 @@
+package se.nbis.lega.cucumber.hooks;
+
+import cucumber.api.java.After;
+import cucumber.api.java.Before;
+import cucumber.api.java8.En;
+import org.apache.commons.io.FileUtils;
+import se.nbis.lega.cucumber.Context;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+public class BeforeAfterHooks implements En {
+
+ private Context context;
+
+ public BeforeAfterHooks(Context context) {
+ this.context = context;
+ }
+
+ @Before
+ public void setUp() throws IOException {
+ File dataFolder = new File("data");
+ dataFolder.mkdir();
+ File rawFile = File.createTempFile("data", ".raw", dataFolder);
+ FileUtils.writeStringToFile(rawFile, "hello", Charset.defaultCharset());
+ context.setDataFolder(dataFolder);
+ context.setRawFile(rawFile);
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ FileUtils.deleteDirectory(context.getDataFolder());
+ String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
+ File cegaUsersFolder = new File(cegaUsersFolderPath);
+ Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
+ }
+
+}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 7e71253d..e9e01aa0 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -1,46 +1,121 @@
package se.nbis.lega.cucumber.steps;
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.model.Bind;
+import com.github.dockerjava.api.model.Container;
+import com.github.dockerjava.api.model.Volume;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
+import net.schmizz.sshj.userauth.UserAuthException;
+import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.UUID;
@Slf4j
public class Authentication implements En {
public Authentication(Context context) {
- Given("^I am a user \"([^\"]*)\"$", context::setUser);
+ Utils utils = context.getUtils();
- Given("^I have a private key$",
- () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/private/cega/users/%s.sec", context.getUser()))));
+ Given("^I am a user$", () -> context.setUser(UUID.randomUUID().toString()));
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ Given("^I have an account at Central EGA$", () -> {
+ DockerClient dockerClient = utils.getDockerClient();
+ String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
+ String name = UUID.randomUUID().toString();
+ String dataFolderName = context.getDataFolder().getName();
+ CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerCmd("nbis/ega:worker").
+ withName(name).
+ withCmd("sleep", "1000").
+ withBinds(new Bind(cegaUsersFolderPath, new Volume("/" + dataFolderName))).
+ exec();
+ dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
try {
- SSHClient ssh = new SSHClient();
- ssh.addHostKeyVerifier(new PromiscuousVerifier());
- ssh.connect("localhost", 2222);
- ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
- context.setSftp(ssh.newSFTPClient());
- } catch (IOException e) {
+ Container tempWorker = utils.findContainer("nbis/ega:worker", name);
+ double password = Math.random();
+ String user = context.getUser();
+ utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
+ String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
+ File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
+ FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ } finally {
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
+ }
+ });
+
+ Given("^I have correct private key$",
+ () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", context.getUser()))));
+
+ Given("^I have incorrect private key$",
+ () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
+
+ When("^my account expires$", () -> {
+ authenticate(context);
+ try {
+ Thread.sleep(1000);
+ utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
+
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> authenticate(context));
+
+ Then("^I am in the local database$", () -> {
+ try {
+ String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
+ String count = output.split(System.getProperty("line.separator"))[2];
+ Assert.assertEquals(1, Integer.parseInt(count.trim()));
+ } catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
}
});
- Then("^I'm logged in successfully$", () -> {
+ Then("^I am not in the local database$", () -> {
try {
- Assert.assertEquals("inbox", context.getSftp().ls("/").iterator().next().getName());
- } catch (IOException e) {
+ String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
+ String count = output.split(System.getProperty("line.separator"))[2];
+ Assert.assertEquals(0, Integer.parseInt(count.trim()));
+ } catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
}
});
+
+ Then("^I'm logged in successfully$", () -> Assert.assertFalse(context.isAuthenticationFailed()));
+
+ Then("^authentication fails$", () -> Assert.assertTrue(context.isAuthenticationFailed()));
+
+ }
+
+ private void authenticate(Context context) {
+ try {
+ SSHClient ssh = new SSHClient();
+ ssh.addHostKeyVerifier(new PromiscuousVerifier());
+ ssh.connect("localhost", 2222);
+ ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
+ context.setSftp(ssh.newSFTPClient());
+ } catch (UserAuthException e) {
+ log.error(e.getMessage(), e);
+ context.setAuthenticationFailed(true);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
index dc0f6ebe..3560a8d7 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -16,10 +16,10 @@ public class Ingestion implements En {
public Ingestion(Context context) {
Utils utils = context.getUtils();
- Given("^I have CEGA MQ username and password$", () -> {
+ Given("^I have CEGA username and password$", () -> {
try {
- context.setCegaMQUser("cega_swe1");
- context.setCegaMQPassword(utils.readTraceProperty("swe1/.trace", "CEGA_MQ_PASSWORD"));
+ context.setCegaMQUser(utils.readTraceProperty("CEGA_MQ_USER"));
+ context.setCegaMQPassword(utils.readTraceProperty("CEGA_MQ_PASSWORD"));
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -29,16 +29,16 @@ public Ingestion(Context context) {
When("^I ingest file from the LocalEGA inbox$", () -> {
try {
File encryptedFile = context.getEncryptedFile();
- utils.executeWithinContainer(utils.findContainer("nbisweden/ega-cega_mq", "/cega_mq"),
- String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s %s --unenc %s --enc %s",
+ utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "cega_mq"),
+ String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
context.getCegaMQUser(),
context.getCegaMQPassword(),
- "swe1",
- "swe1",
+ utils.readTraceProperty("CEGA_MQ_VHOST"),
context.getUser(),
encryptedFile.getName(),
utils.calculateMD5(context.getRawFile()),
utils.calculateMD5(encryptedFile)).split(" "));
+ Thread.sleep(1000);
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -47,12 +47,9 @@ public Ingestion(Context context) {
Then("^the file is ingested successfully$", () -> {
try {
- Thread.sleep(1000);
- String query = String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName());
- String output = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-db", "/ega_db_swe1"),
- "psql", "-U", utils.readTraceProperty("swe1/.trace", "DB_USER"), "-d", "lega", "-c", query);
+ String output = utils.executeDBQuery(String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName()));
String vaultFileName = output.split(System.getProperty("line.separator"))[2];
- String cat = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-common", "/ega_vault_swe1"), "cat", vaultFileName.trim());
+ String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "ega_vault"), "cat", vaultFileName.trim());
Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
@@ -61,4 +58,4 @@ public Ingestion(Context context) {
});
}
-}
+}
\ No newline at end of file
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index ede86b40..dcae27d6 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -26,28 +26,32 @@ public Uploading(Context context) {
Given("^I have an encrypted file$", () -> {
DockerClient dockerClient = utils.getDockerClient();
File rawFile = context.getRawFile();
+ String dataFolderName = context.getDataFolder().getName();
+ Volume dataVolume = new Volume("/" + dataFolderName);
+ Volume gpgVolume = new Volume("/root/.gnupg");
+ CreateContainerResponse createContainerResponse = null;
try {
- Volume dataVolume = new Volume("/data");
- Volume gpgVolume = new Volume("/root/.gnupg");
- CreateContainerResponse createContainerResponse = dockerClient.
- createContainerCmd("nbisweden/ega-worker").
+ createContainerResponse = dockerClient.
+ createContainerCmd("nbis/ega:worker").
withVolumes(dataVolume, gpgVolume).
- withBinds(new Bind(context.getDataFolder().getAbsolutePath(), dataVolume),
- new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/private/swe1/gpg", gpgVolume, AccessMode.ro)).
- withCmd("gpg2", //utils.readTraceProperty("swe1/.trace", "GPG exec"),
- "-r",
- utils.readTraceProperty("swe1/.trace", "GPG_EMAIL"),
- "-e",
- "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
+ withBinds(new Bind(Paths.get(dataFolderName).toAbsolutePath().toString(), dataVolume),
+ new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
+ withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", String.format("/%s/%s.enc", dataFolderName, rawFile.getName()), String.format("/%s/%s", dataFolderName, rawFile.getName())).
exec();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ Assert.fail(e.getMessage());
+ }
+ try {
dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback);
resultCallback.awaitCompletion();
- dockerClient.removeContainerCmd(createContainerResponse.getId()).exec();
- } catch (IOException | InterruptedException e) {
+ } catch (InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
+ } finally {
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
}
context.setEncryptedFile(new File(rawFile.getAbsolutePath() + ".enc"));
});
@@ -58,7 +62,6 @@ public Uploading(Context context) {
context.getSftp().put(encryptedFile.getAbsolutePath(), encryptedFile.getName());
} catch (IOException e) {
log.error(e.getMessage(), e);
- Assert.fail(e.getMessage());
}
});
@@ -72,4 +75,4 @@ public Uploading(Context context) {
});
}
-}
+}
\ No newline at end of file
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index 4828a3fb..166d0211 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -1,8 +1,36 @@
Feature: Authentication
As a user I want to be able to authenticate against LocalEGA inbox
- Scenario: Authenticate against LocalEGA inbox using private key
- Given I am a user "john"
- And I have a private key
+ Scenario: User population in LocalEGA DB from Central EGA
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then I am in the local database
+
+ Scenario: User doesn't exist in Central EGA, but tries to authenticate against LocalEGA inbox
+ Given I am a user
+ And I have correct private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
+ Scenario: User exists in Central EGA, but uses incorrect private key for authentication
+ Given I am a user
+ And I have an account at Central EGA
+ And I have incorrect private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
+ Scenario: User exists in Central EGA, but his account has expired
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
+ When my account expires
+ Then I am not in the local database
+
+ Scenario: User exists in Central EGA and uses correct private key for authentication
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then I'm logged in successfully
\ No newline at end of file
diff --git a/tests/src/test/resources/cucumber/features/ingestion.feature b/tests/src/test/resources/cucumber/features/ingestion.feature
index cd64dc43..65dfb331 100644
--- a/tests/src/test/resources/cucumber/features/ingestion.feature
+++ b/tests/src/test/resources/cucumber/features/ingestion.feature
@@ -2,8 +2,9 @@ Feature: Ingestion
As a user I want to be able to ingest files from the LocalEGA inbox
Scenario: Ingest files from the LocalEGA inbox
- Given I am a user "john"
- And I have a private key
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
And I upload encrypted file to the LocalEGA inbox via SFTP
diff --git a/tests/src/test/resources/cucumber/features/uploading.feature b/tests/src/test/resources/cucumber/features/uploading.feature
index 12abdbf5..9adf5c3c 100644
--- a/tests/src/test/resources/cucumber/features/uploading.feature
+++ b/tests/src/test/resources/cucumber/features/uploading.feature
@@ -2,8 +2,9 @@ Feature: Uploading
As a user I want to be able to upload files to the LocalEGA inbox
Scenario: Upload files to the LocalEGA inbox
- Given I am a user "john"
- And I have a private key
+ Given I am a user
+ And I have an account at Central EGA
+ And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
When I upload encrypted file to the LocalEGA inbox via SFTP
From 613071faf6972d591f43cc1b39aa6bb04cf5d205 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 16:52:48 +0100
Subject: [PATCH 103/528] Fix SFTP library bug (work-around). Use temp users in
testing.
---
.../lega/cucumber/hooks/BeforeAfterHooks.java | 3 ++-
.../nbis/lega/cucumber/steps/Authentication.java | 16 ++++++++++++----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index 30c3fb9d..bbf24f9f 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -32,11 +32,12 @@ public void setUp() throws IOException {
}
@After
- public void tearDown() throws IOException {
+ public void tearDown() throws IOException, InterruptedException {
FileUtils.deleteDirectory(context.getDataFolder());
String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
File cegaUsersFolder = new File(cegaUsersFolderPath);
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
+ context.getUtils().executeDBQuery(String.format("delete from users where elixir_id = '%s'", context.getUser()));
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index e9e01aa0..43d3c80c 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -47,6 +47,7 @@ public Authentication(Context context) {
String user = context.getUser();
utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("chmod 400 /%s/%s.sec", dataFolderName, user).split(" "));
String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
@@ -73,7 +74,9 @@ public Authentication(Context context) {
}
});
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> authenticate(context));
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ authenticate(context);
+ });
Then("^I am in the local database$", () -> {
try {
@@ -104,17 +107,22 @@ public Authentication(Context context) {
}
private void authenticate(Context context) {
+ // need to retry twice due to bug in SSHJ library
+ retryAuthenticationAttempt(context);
+ retryAuthenticationAttempt(context);
+ }
+
+ private void retryAuthenticationAttempt(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
context.setSftp(ssh.newSFTPClient());
- } catch (UserAuthException e) {
+ context.setAuthenticationFailed(false);
+ } catch (Exception e) {
log.error(e.getMessage(), e);
context.setAuthenticationFailed(true);
- } catch (IOException e) {
- log.error(e.getMessage(), e);
}
}
From 525641067188556c17ee54629a61e069f145aa8b Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 17:17:35 +0100
Subject: [PATCH 104/528] Reuse single test user across all scenarios.
---
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 43d3c80c..1dfba558 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -9,7 +9,6 @@
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
-import net.schmizz.sshj.userauth.UserAuthException;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import se.nbis.lega.cucumber.Context;
@@ -27,7 +26,7 @@ public class Authentication implements En {
public Authentication(Context context) {
Utils utils = context.getUtils();
- Given("^I am a user$", () -> context.setUser(UUID.randomUUID().toString()));
+ Given("^I am a user$", () -> context.setUser("test"));
Given("^I have an account at Central EGA$", () -> {
DockerClient dockerClient = utils.getDockerClient();
@@ -107,12 +106,6 @@ public Authentication(Context context) {
}
private void authenticate(Context context) {
- // need to retry twice due to bug in SSHJ library
- retryAuthenticationAttempt(context);
- retryAuthenticationAttempt(context);
- }
-
- private void retryAuthenticationAttempt(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
From 5352af52a5d839b6bcda8ba00503a6157bd48be3 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 21:26:01 +0100
Subject: [PATCH 105/528] Change keys permissions in code, run tests as root.
---
.travis.yml | 2 +-
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 8 ++++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 281ba939..4522746f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,7 +17,7 @@ install:
script:
- cd ../tests
- - mvn test -B
+ - sudo mvn test -B
after_success:
- |
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 1dfba558..76de69d7 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -16,8 +16,11 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
+import java.util.Collections;
import java.util.UUID;
@Slf4j
@@ -46,7 +49,6 @@ public Authentication(Context context) {
String user = context.getUser();
utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
- utils.executeWithinContainer(tempWorker, String.format("chmod 400 /%s/%s.sec", dataFolderName, user).split(" "));
String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
@@ -110,7 +112,9 @@ private void authenticate(Context context) {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
- ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
+ File privateKey = context.getPrivateKey();
+ Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
+ ssh.authPublickey(context.getUser(), privateKey.getPath());
context.setSftp(ssh.newSFTPClient());
context.setAuthenticationFailed(false);
} catch (Exception e) {
From ca4cd24791eeff57bdd6ab6217db264411215e89 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sun, 5 Nov 2017 13:20:12 +0100
Subject: [PATCH 106/528] Cleanup inbox after tests execution.
---
.../java/se/nbis/lega/cucumber/Context.java | 2 ++
.../java/se/nbis/lega/cucumber/Utils.java | 17 ++++++++++--
.../lega/cucumber/hooks/BeforeAfterHooks.java | 9 ++++---
.../lega/cucumber/steps/Authentication.java | 26 ++++++++++++-------
4 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Context.java b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
index d7819dfd..11fe73a0 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Context.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
@@ -1,6 +1,7 @@
package se.nbis.lega.cucumber;
import lombok.Data;
+import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.sftp.SFTPClient;
import java.io.File;
@@ -14,6 +15,7 @@ public class Context {
private File privateKey;
private String cegaMQUser;
private String cegaMQPassword;
+ private SSHClient ssh;
private SFTPClient sftp;
private File dataFolder;
private File rawFile;
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index f8e9f956..af3bd84d 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -71,11 +71,24 @@ public String executeDBQuery(String query) throws IOException, InterruptedExcept
return executeWithinContainer(findContainer("nbis/ega:db", "ega_db"), "psql", "-U", readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
}
+ /**
+ * Checks if user exists in the local database.
+ *
+ * @param user Username.
+ * @return true
if user exists, false
otherwise.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public boolean isUserExistInDB(String user) throws IOException, InterruptedException {
+ String output = executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", user));
+ return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
+ }
+
/**
* Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
*
- * @param from Folder to mount from.
- * @param to Folder to mount to.
+ * @param from Folder to mount from.
+ * @param to Folder to mount to.
* @param command Command to execute.
* @throws InterruptedException In case the command execution is interrupted.
*/
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index bbf24f9f..b685ff08 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -5,9 +5,9 @@
import cucumber.api.java8.En;
import org.apache.commons.io.FileUtils;
import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
import java.io.File;
-import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Paths;
@@ -36,8 +36,11 @@ public void tearDown() throws IOException, InterruptedException {
FileUtils.deleteDirectory(context.getDataFolder());
String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
File cegaUsersFolder = new File(cegaUsersFolderPath);
- Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
- context.getUtils().executeDBQuery(String.format("delete from users where elixir_id = '%s'", context.getUser()));
+ Utils utils = context.getUtils();
+ String user = context.getUser();
+ Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
+ utils.executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ utils.executeWithinContainer(utils.findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 76de69d7..7fb7d6f1 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -66,7 +66,8 @@ public Authentication(Context context) {
() -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
When("^my account expires$", () -> {
- authenticate(context);
+ connect(context);
+ disconnect(context);
try {
Thread.sleep(1000);
utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
@@ -76,14 +77,12 @@ public Authentication(Context context) {
});
When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
- authenticate(context);
+ connect(context);
});
Then("^I am in the local database$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
- String count = output.split(System.getProperty("line.separator"))[2];
- Assert.assertEquals(1, Integer.parseInt(count.trim()));
+ Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -92,9 +91,7 @@ public Authentication(Context context) {
Then("^I am not in the local database$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
- String count = output.split(System.getProperty("line.separator"))[2];
- Assert.assertEquals(0, Integer.parseInt(count.trim()));
+ Assert.assertFalse(utils.isUserExistInDB(context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -107,7 +104,7 @@ public Authentication(Context context) {
}
- private void authenticate(Context context) {
+ private void connect(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
@@ -115,6 +112,8 @@ private void authenticate(Context context) {
File privateKey = context.getPrivateKey();
Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
ssh.authPublickey(context.getUser(), privateKey.getPath());
+
+ context.setSsh(ssh);
context.setSftp(ssh.newSFTPClient());
context.setAuthenticationFailed(false);
} catch (Exception e) {
@@ -123,4 +122,13 @@ private void authenticate(Context context) {
}
}
+ private void disconnect(Context context) {
+ try {
+ context.getSftp().close();
+ context.getSsh().disconnect();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+
}
\ No newline at end of file
From 661439d920ee52b6f7ad35a03bb942b106a580fe Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Tue, 7 Nov 2017 12:35:59 +0100
Subject: [PATCH 107/528] Refactoring.
---
.../java/se/nbis/lega/cucumber/Utils.java | 24 ++++++++++++++++++-
.../lega/cucumber/hooks/BeforeAfterHooks.java | 4 ++--
.../lega/cucumber/steps/Authentication.java | 11 +++++++++
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index af3bd84d..68331979 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -72,7 +72,7 @@ public String executeDBQuery(String query) throws IOException, InterruptedExcept
}
/**
- * Checks if user exists in the local database.
+ * Checks if the user exists in the local database.
*
* @param user Username.
* @return true
if user exists, false
otherwise.
@@ -84,6 +84,28 @@ public boolean isUserExistInDB(String user) throws IOException, InterruptedExcep
return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
}
+ /**
+ * Removes the user from the local database.
+ *
+ * @param user Username.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public void removeUserFromDB(String user) throws IOException, InterruptedException {
+ executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ }
+
+ /**
+ * Removes the user from the inbox.
+ *
+ * @param user Username.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public void removeUserFromInbox(String user) throws IOException, InterruptedException {
+ executeWithinContainer(findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ }
+
/**
* Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
*
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index b685ff08..aba27ac2 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -39,8 +39,8 @@ public void tearDown() throws IOException, InterruptedException {
Utils utils = context.getUtils();
String user = context.getUser();
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
- utils.executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
- utils.executeWithinContainer(utils.findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ utils.removeUserFromDB(user);
+ utils.removeUserFromInbox(user);
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 7fb7d6f1..57b5dd40 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -5,6 +5,7 @@
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Volume;
+import cucumber.api.PendingException;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
@@ -80,6 +81,16 @@ public Authentication(Context context) {
connect(context);
});
+ When("^inbox is not created for me$", () -> {
+ try {
+ disconnect(context);
+ utils.removeUserFromInbox(context.getUser());
+ connect(context);
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
+
Then("^I am in the local database$", () -> {
try {
Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
From 0b5a4b29797efedab4be451847585953bc3c2a48 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 14:30:23 +0100
Subject: [PATCH 108/528] Refactor tests, add authentication tests.
---
.../java/se/nbis/lega/cucumber/Utils.java | 41 ++-------------
.../lega/cucumber/hooks/BeforeAfterHooks.java | 10 ++--
.../lega/cucumber/steps/Authentication.java | 52 +++++--------------
3 files changed, 20 insertions(+), 83 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index 68331979..0a0e9e65 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -71,46 +71,11 @@ public String executeDBQuery(String query) throws IOException, InterruptedExcept
return executeWithinContainer(findContainer("nbis/ega:db", "ega_db"), "psql", "-U", readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
}
- /**
- * Checks if the user exists in the local database.
- *
- * @param user Username.
- * @return true
if user exists, false
otherwise.
- * @throws IOException In case of output error.
- * @throws InterruptedException In case the query execution is interrupted.
- */
- public boolean isUserExistInDB(String user) throws IOException, InterruptedException {
- String output = executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", user));
- return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
- }
-
- /**
- * Removes the user from the local database.
- *
- * @param user Username.
- * @throws IOException In case of output error.
- * @throws InterruptedException In case the query execution is interrupted.
- */
- public void removeUserFromDB(String user) throws IOException, InterruptedException {
- executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
- }
-
- /**
- * Removes the user from the inbox.
- *
- * @param user Username.
- * @throws IOException In case of output error.
- * @throws InterruptedException In case the query execution is interrupted.
- */
- public void removeUserFromInbox(String user) throws IOException, InterruptedException {
- executeWithinContainer(findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
- }
-
/**
* Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
*
- * @param from Folder to mount from.
- * @param to Folder to mount to.
+ * @param from Folder to mount from.
+ * @param to Folder to mount to.
* @param command Command to execute.
* @throws InterruptedException In case the command execution is interrupted.
*/
@@ -139,7 +104,7 @@ public void spawnWorkerAndExecute(String from, String to, String... command) thr
* @throws IOException In case it's not possible to read trace file.
*/
public String readTraceProperty(String fileName, String property) throws IOException {
- File trace = new File(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/private/" + fileName);
+ File trace = new File(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/" + fileName);
return FileUtils.readLines(trace, Charset.defaultCharset()).
stream().
filter(l -> l.startsWith(property)).
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index aba27ac2..30c3fb9d 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -5,9 +5,9 @@
import cucumber.api.java8.En;
import org.apache.commons.io.FileUtils;
import se.nbis.lega.cucumber.Context;
-import se.nbis.lega.cucumber.Utils;
import java.io.File;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Paths;
@@ -32,15 +32,11 @@ public void setUp() throws IOException {
}
@After
- public void tearDown() throws IOException, InterruptedException {
+ public void tearDown() throws IOException {
FileUtils.deleteDirectory(context.getDataFolder());
String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
File cegaUsersFolder = new File(cegaUsersFolderPath);
- Utils utils = context.getUtils();
- String user = context.getUser();
- Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
- utils.removeUserFromDB(user);
- utils.removeUserFromInbox(user);
+ Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 57b5dd40..e9e01aa0 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -5,11 +5,11 @@
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Volume;
-import cucumber.api.PendingException;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
+import net.schmizz.sshj.userauth.UserAuthException;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import se.nbis.lega.cucumber.Context;
@@ -17,11 +17,8 @@
import java.io.File;
import java.io.IOException;
-import java.nio.file.Files;
import java.nio.file.Paths;
-import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
-import java.util.Collections;
import java.util.UUID;
@Slf4j
@@ -30,7 +27,7 @@ public class Authentication implements En {
public Authentication(Context context) {
Utils utils = context.getUtils();
- Given("^I am a user$", () -> context.setUser("test"));
+ Given("^I am a user$", () -> context.setUser(UUID.randomUUID().toString()));
Given("^I have an account at Central EGA$", () -> {
DockerClient dockerClient = utils.getDockerClient();
@@ -67,8 +64,7 @@ public Authentication(Context context) {
() -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
When("^my account expires$", () -> {
- connect(context);
- disconnect(context);
+ authenticate(context);
try {
Thread.sleep(1000);
utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
@@ -77,23 +73,13 @@ public Authentication(Context context) {
}
});
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
- connect(context);
- });
-
- When("^inbox is not created for me$", () -> {
- try {
- disconnect(context);
- utils.removeUserFromInbox(context.getUser());
- connect(context);
- } catch (IOException | InterruptedException e) {
- log.error(e.getMessage(), e);
- }
- });
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> authenticate(context));
Then("^I am in the local database$", () -> {
try {
- Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
+ String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
+ String count = output.split(System.getProperty("line.separator"))[2];
+ Assert.assertEquals(1, Integer.parseInt(count.trim()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -102,7 +88,9 @@ public Authentication(Context context) {
Then("^I am not in the local database$", () -> {
try {
- Assert.assertFalse(utils.isUserExistInDB(context.getUser()));
+ String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
+ String count = output.split(System.getProperty("line.separator"))[2];
+ Assert.assertEquals(0, Integer.parseInt(count.trim()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -115,29 +103,17 @@ public Authentication(Context context) {
}
- private void connect(Context context) {
+ private void authenticate(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
- File privateKey = context.getPrivateKey();
- Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
- ssh.authPublickey(context.getUser(), privateKey.getPath());
-
- context.setSsh(ssh);
+ ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
context.setSftp(ssh.newSFTPClient());
- context.setAuthenticationFailed(false);
- } catch (Exception e) {
+ } catch (UserAuthException e) {
log.error(e.getMessage(), e);
context.setAuthenticationFailed(true);
- }
- }
-
- private void disconnect(Context context) {
- try {
- context.getSftp().close();
- context.getSsh().disconnect();
- } catch (Exception e) {
+ } catch (IOException e) {
log.error(e.getMessage(), e);
}
}
From 58836e3c136e225f5a00d9acb9f8ee4329d3a333 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 16:52:48 +0100
Subject: [PATCH 109/528] Fix SFTP library bug (work-around). Use temp users in
testing.
---
.../lega/cucumber/hooks/BeforeAfterHooks.java | 3 ++-
.../nbis/lega/cucumber/steps/Authentication.java | 16 ++++++++++++----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index 30c3fb9d..bbf24f9f 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -32,11 +32,12 @@ public void setUp() throws IOException {
}
@After
- public void tearDown() throws IOException {
+ public void tearDown() throws IOException, InterruptedException {
FileUtils.deleteDirectory(context.getDataFolder());
String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
File cegaUsersFolder = new File(cegaUsersFolderPath);
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
+ context.getUtils().executeDBQuery(String.format("delete from users where elixir_id = '%s'", context.getUser()));
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index e9e01aa0..43d3c80c 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -47,6 +47,7 @@ public Authentication(Context context) {
String user = context.getUser();
utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("chmod 400 /%s/%s.sec", dataFolderName, user).split(" "));
String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
@@ -73,7 +74,9 @@ public Authentication(Context context) {
}
});
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> authenticate(context));
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
+ authenticate(context);
+ });
Then("^I am in the local database$", () -> {
try {
@@ -104,17 +107,22 @@ public Authentication(Context context) {
}
private void authenticate(Context context) {
+ // need to retry twice due to bug in SSHJ library
+ retryAuthenticationAttempt(context);
+ retryAuthenticationAttempt(context);
+ }
+
+ private void retryAuthenticationAttempt(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
context.setSftp(ssh.newSFTPClient());
- } catch (UserAuthException e) {
+ context.setAuthenticationFailed(false);
+ } catch (Exception e) {
log.error(e.getMessage(), e);
context.setAuthenticationFailed(true);
- } catch (IOException e) {
- log.error(e.getMessage(), e);
}
}
From b10002a11ed1d4389060a2d020f4633c88f49390 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 17:17:35 +0100
Subject: [PATCH 110/528] Reuse single test user across all scenarios.
---
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 43d3c80c..1dfba558 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -9,7 +9,6 @@
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
-import net.schmizz.sshj.userauth.UserAuthException;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import se.nbis.lega.cucumber.Context;
@@ -27,7 +26,7 @@ public class Authentication implements En {
public Authentication(Context context) {
Utils utils = context.getUtils();
- Given("^I am a user$", () -> context.setUser(UUID.randomUUID().toString()));
+ Given("^I am a user$", () -> context.setUser("test"));
Given("^I have an account at Central EGA$", () -> {
DockerClient dockerClient = utils.getDockerClient();
@@ -107,12 +106,6 @@ public Authentication(Context context) {
}
private void authenticate(Context context) {
- // need to retry twice due to bug in SSHJ library
- retryAuthenticationAttempt(context);
- retryAuthenticationAttempt(context);
- }
-
- private void retryAuthenticationAttempt(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
From b6130d127c70620131d8ff76971602d05acbc33b Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sat, 4 Nov 2017 21:26:01 +0100
Subject: [PATCH 111/528] Change keys permissions in code, run tests as root.
---
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 1dfba558..76de69d7 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -16,8 +16,11 @@
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
+import java.util.Collections;
import java.util.UUID;
@Slf4j
@@ -46,7 +49,6 @@ public Authentication(Context context) {
String user = context.getUser();
utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
- utils.executeWithinContainer(tempWorker, String.format("chmod 400 /%s/%s.sec", dataFolderName, user).split(" "));
String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
@@ -110,7 +112,9 @@ private void authenticate(Context context) {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
- ssh.authPublickey(context.getUser(), context.getPrivateKey().getPath());
+ File privateKey = context.getPrivateKey();
+ Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
+ ssh.authPublickey(context.getUser(), privateKey.getPath());
context.setSftp(ssh.newSFTPClient());
context.setAuthenticationFailed(false);
} catch (Exception e) {
From 3f0b7f326c03190e0517e5fa8c875d9e14fac590 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Sun, 5 Nov 2017 13:20:12 +0100
Subject: [PATCH 112/528] Cleanup inbox after tests execution.
---
.../java/se/nbis/lega/cucumber/Utils.java | 17 ++++++++++--
.../lega/cucumber/hooks/BeforeAfterHooks.java | 9 ++++---
.../lega/cucumber/steps/Authentication.java | 26 ++++++++++++-------
3 files changed, 38 insertions(+), 14 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index 0a0e9e65..c650892a 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -71,11 +71,24 @@ public String executeDBQuery(String query) throws IOException, InterruptedExcept
return executeWithinContainer(findContainer("nbis/ega:db", "ega_db"), "psql", "-U", readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
}
+ /**
+ * Checks if user exists in the local database.
+ *
+ * @param user Username.
+ * @return true
if user exists, false
otherwise.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public boolean isUserExistInDB(String user) throws IOException, InterruptedException {
+ String output = executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", user));
+ return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
+ }
+
/**
* Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
*
- * @param from Folder to mount from.
- * @param to Folder to mount to.
+ * @param from Folder to mount from.
+ * @param to Folder to mount to.
* @param command Command to execute.
* @throws InterruptedException In case the command execution is interrupted.
*/
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index bbf24f9f..b685ff08 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -5,9 +5,9 @@
import cucumber.api.java8.En;
import org.apache.commons.io.FileUtils;
import se.nbis.lega.cucumber.Context;
+import se.nbis.lega.cucumber.Utils;
import java.io.File;
-import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Paths;
@@ -36,8 +36,11 @@ public void tearDown() throws IOException, InterruptedException {
FileUtils.deleteDirectory(context.getDataFolder());
String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
File cegaUsersFolder = new File(cegaUsersFolderPath);
- Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(context.getUser()))).forEach(File::delete);
- context.getUtils().executeDBQuery(String.format("delete from users where elixir_id = '%s'", context.getUser()));
+ Utils utils = context.getUtils();
+ String user = context.getUser();
+ Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
+ utils.executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ utils.executeWithinContainer(utils.findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 76de69d7..7fb7d6f1 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -66,7 +66,8 @@ public Authentication(Context context) {
() -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
When("^my account expires$", () -> {
- authenticate(context);
+ connect(context);
+ disconnect(context);
try {
Thread.sleep(1000);
utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
@@ -76,14 +77,12 @@ public Authentication(Context context) {
});
When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
- authenticate(context);
+ connect(context);
});
Then("^I am in the local database$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
- String count = output.split(System.getProperty("line.separator"))[2];
- Assert.assertEquals(1, Integer.parseInt(count.trim()));
+ Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -92,9 +91,7 @@ public Authentication(Context context) {
Then("^I am not in the local database$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", context.getUser()));
- String count = output.split(System.getProperty("line.separator"))[2];
- Assert.assertEquals(0, Integer.parseInt(count.trim()));
+ Assert.assertFalse(utils.isUserExistInDB(context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -107,7 +104,7 @@ public Authentication(Context context) {
}
- private void authenticate(Context context) {
+ private void connect(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
@@ -115,6 +112,8 @@ private void authenticate(Context context) {
File privateKey = context.getPrivateKey();
Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
ssh.authPublickey(context.getUser(), privateKey.getPath());
+
+ context.setSsh(ssh);
context.setSftp(ssh.newSFTPClient());
context.setAuthenticationFailed(false);
} catch (Exception e) {
@@ -123,4 +122,13 @@ private void authenticate(Context context) {
}
}
+ private void disconnect(Context context) {
+ try {
+ context.getSftp().close();
+ context.getSsh().disconnect();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+
}
\ No newline at end of file
From 6b254cb5a2b66805ac78995e22ecf0a3a31adb82 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Tue, 7 Nov 2017 12:35:59 +0100
Subject: [PATCH 113/528] Refactoring.
---
.../java/se/nbis/lega/cucumber/Utils.java | 24 ++++++++++++++++++-
.../lega/cucumber/hooks/BeforeAfterHooks.java | 4 ++--
.../lega/cucumber/steps/Authentication.java | 11 +++++++++
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index c650892a..bd0cf5b0 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -72,7 +72,7 @@ public String executeDBQuery(String query) throws IOException, InterruptedExcept
}
/**
- * Checks if user exists in the local database.
+ * Checks if the user exists in the local database.
*
* @param user Username.
* @return true
if user exists, false
otherwise.
@@ -84,6 +84,28 @@ public boolean isUserExistInDB(String user) throws IOException, InterruptedExcep
return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
}
+ /**
+ * Removes the user from the local database.
+ *
+ * @param user Username.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public void removeUserFromDB(String user) throws IOException, InterruptedException {
+ executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ }
+
+ /**
+ * Removes the user from the inbox.
+ *
+ * @param user Username.
+ * @throws IOException In case of output error.
+ * @throws InterruptedException In case the query execution is interrupted.
+ */
+ public void removeUserFromInbox(String user) throws IOException, InterruptedException {
+ executeWithinContainer(findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ }
+
/**
* Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
*
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index b685ff08..aba27ac2 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -39,8 +39,8 @@ public void tearDown() throws IOException, InterruptedException {
Utils utils = context.getUtils();
String user = context.getUser();
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
- utils.executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
- utils.executeWithinContainer(utils.findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ utils.removeUserFromDB(user);
+ utils.removeUserFromInbox(user);
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 7fb7d6f1..57b5dd40 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -5,6 +5,7 @@
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Volume;
+import cucumber.api.PendingException;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
@@ -80,6 +81,16 @@ public Authentication(Context context) {
connect(context);
});
+ When("^inbox is not created for me$", () -> {
+ try {
+ disconnect(context);
+ utils.removeUserFromInbox(context.getUser());
+ connect(context);
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
+
Then("^I am in the local database$", () -> {
try {
Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
From bdf41799a119fe8b36c4340e7e88196286314eee Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Thu, 9 Nov 2017 22:51:09 +0100
Subject: [PATCH 114/528] Align tests with new multi-ega functionality.
---
.../java/se/nbis/lega/cucumber/Context.java | 5 ++
.../java/se/nbis/lega/cucumber/Utils.java | 57 ++++++++-----
.../lega/cucumber/hooks/BeforeAfterHooks.java | 11 ++-
.../lega/cucumber/steps/Authentication.java | 83 +++++++++++--------
.../nbis/lega/cucumber/steps/Ingestion.java | 18 ++--
.../nbis/lega/cucumber/steps/Uploading.java | 8 +-
.../cucumber/features/authentication.feature | 20 +++--
.../cucumber/features/ingestion.feature | 4 +-
.../cucumber/features/uploading.feature | 4 +-
9 files changed, 132 insertions(+), 78 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Context.java b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
index 11fe73a0..b67b4b75 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Context.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Context.java
@@ -5,6 +5,7 @@
import net.schmizz.sshj.sftp.SFTPClient;
import java.io.File;
+import java.util.List;
@Data
public class Context {
@@ -12,9 +13,13 @@ public class Context {
private Utils utils = new Utils();
private String user;
+ private List instances;
+ private String targetInstance;
private File privateKey;
private String cegaMQUser;
private String cegaMQPassword;
+ private String cegaMQVHost;
+ private String routingKey;
private SSHClient ssh;
private SFTPClient sftp;
private File dataFolder;
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index bd0cf5b0..2d016ebf 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -35,6 +35,15 @@ public Utils() {
this.dockerClient = DockerClientBuilder.getInstance(DefaultDockerClientConfig.createDefaultConfigBuilder().build()).build();
}
+ /**
+ * Gets absolute path or a private folder.
+ *
+ * @return Absolute path or a private folder.
+ */
+ public String getPrivateFolderPath() {
+ return Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private";
+ }
+
/**
* Executes shell command within specified container.
*
@@ -62,66 +71,71 @@ public String executeWithinContainer(Container container, String... command) thr
/**
* Executes PSQL query.
*
- * @param query Query to execute.
+ * @param instance LocalEGA site.
+ * @param query Query to execute.
* @return Query output.
* @throws IOException In case of output error.
* @throws InterruptedException In case the query execution is interrupted.
*/
- public String executeDBQuery(String query) throws IOException, InterruptedException {
- return executeWithinContainer(findContainer("nbis/ega:db", "ega_db"), "psql", "-U", readTraceProperty("DB_USER"), "-d", "lega", "-c", query);
+ public String executeDBQuery(String instance, String query) throws IOException, InterruptedException {
+ return executeWithinContainer(findContainer("nbisweden/ega-db", "ega_db_" + instance), "psql", "-U", readTraceProperty(instance, "DB_USER"), "-d", "lega", "-c", query);
}
/**
* Checks if the user exists in the local database.
*
- * @param user Username.
+ * @param instance LocalEGA site.
+ * @param user Username.
* @return true
if user exists, false
otherwise.
* @throws IOException In case of output error.
* @throws InterruptedException In case the query execution is interrupted.
*/
- public boolean isUserExistInDB(String user) throws IOException, InterruptedException {
- String output = executeDBQuery(String.format("select count(*) from users where elixir_id = '%s'", user));
+ public boolean isUserExistInDB(String instance, String user) throws IOException, InterruptedException {
+ String output = executeDBQuery(instance, String.format("select count(*) from users where elixir_id = '%s'", user));
return "1".equals(output.split(System.getProperty("line.separator"))[2].trim());
}
/**
* Removes the user from the local database.
*
- * @param user Username.
+ * @param instance LocalEGA site.
+ * @param user Username.
* @throws IOException In case of output error.
* @throws InterruptedException In case the query execution is interrupted.
*/
- public void removeUserFromDB(String user) throws IOException, InterruptedException {
- executeDBQuery(String.format("delete from users where elixir_id = '%s'", user));
+ public void removeUserFromDB(String instance, String user) throws IOException, InterruptedException {
+ executeDBQuery(instance, String.format("delete from users where elixir_id = '%s'", user));
}
/**
* Removes the user from the inbox.
*
- * @param user Username.
+ * @param instance LocalEGA site.
+ * @param user Username.
* @throws IOException In case of output error.
* @throws InterruptedException In case the query execution is interrupted.
*/
- public void removeUserFromInbox(String user) throws IOException, InterruptedException {
- executeWithinContainer(findContainer("nbis/ega:inbox", "ega_inbox"), String.format("rm -rf /ega/inbox/%s", user).split(" "));
+ public void removeUserFromInbox(String instance, String user) throws IOException, InterruptedException {
+ executeWithinContainer(findContainer("nbisweden/ega-inbox", "ega_inbox_" + instance), String.format("rm -rf /ega/inbox/%s", user).split(" "));
}
/**
- * Spawns "nbis/ega:worker" container, mounts data folder there and executes a command.
+ * Spawns "nbisweden/ega-worker" container, mounts data folder there and executes a command.
*
- * @param from Folder to mount from.
- * @param to Folder to mount to.
- * @param command Command to execute.
+ * @param instance LocalEGA site.
+ * @param from Folder to mount from.
+ * @param to Folder to mount to.
+ * @param command Command to execute.
* @throws InterruptedException In case the command execution is interrupted.
*/
- public void spawnWorkerAndExecute(String from, String to, String... command) throws InterruptedException {
+ public void spawnWorkerAndExecute(String instance, String from, String to, String... command) throws InterruptedException {
Volume dataVolume = new Volume(to);
Volume gpgVolume = new Volume("/root/.gnupg");
CreateContainerResponse createContainerResponse = dockerClient.
- createContainerCmd("nbis/ega:worker").
+ createContainerCmd("nbisweden/ega-worker").
withVolumes(dataVolume, gpgVolume).
withBinds(new Bind(from, dataVolume),
- new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
+ new Bind(String.format("%s/%s/gpg", getPrivateFolderPath(), instance), gpgVolume, AccessMode.ro)).
withCmd(command).
exec();
dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
@@ -134,12 +148,13 @@ public void spawnWorkerAndExecute(String from, String to, String... command) thr
/**
* Reads property from the trace file.
*
+ * @param instance LocalEGA site.
* @param property Property name.
* @return Property value.
* @throws IOException In case it's not possible to read trace file.
*/
- public String readTraceProperty(String fileName, String property) throws IOException {
- File trace = new File(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/" + fileName);
+ public String readTraceProperty(String instance, String property) throws IOException {
+ File trace = new File(getPrivateFolderPath() + "/.trace." + instance);
return FileUtils.readLines(trace, Charset.defaultCharset()).
stream().
filter(l -> l.startsWith(property)).
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index aba27ac2..c68e4631 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -10,7 +10,6 @@
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
-import java.nio.file.Paths;
import java.util.Arrays;
public class BeforeAfterHooks implements En {
@@ -33,14 +32,14 @@ public void setUp() throws IOException {
@After
public void tearDown() throws IOException, InterruptedException {
- FileUtils.deleteDirectory(context.getDataFolder());
- String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
- File cegaUsersFolder = new File(cegaUsersFolderPath);
Utils utils = context.getUtils();
+ FileUtils.deleteDirectory(context.getDataFolder());
+ String targetInstance = context.getTargetInstance();
+ File cegaUsersFolder = new File(utils.getPrivateFolderPath() + "/cega/users/" + targetInstance);
String user = context.getUser();
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
- utils.removeUserFromDB(user);
- utils.removeUserFromInbox(user);
+ utils.removeUserFromDB(targetInstance, user);
+ utils.removeUserFromInbox(targetInstance, user);
}
}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 57b5dd40..0b4cad36 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -5,7 +5,7 @@
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.Volume;
-import cucumber.api.PendingException;
+import cucumber.api.DataTable;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;
@@ -18,7 +18,6 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
-import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
import java.util.Collections;
@@ -30,48 +29,65 @@ public class Authentication implements En {
public Authentication(Context context) {
Utils utils = context.getUtils();
- Given("^I am a user$", () -> context.setUser("test"));
+ Given("^I am a user of LocalEGA instances:$", (DataTable instances) -> {
+ context.setUser("test");
+ context.setInstances(instances.asList(String.class));
+ });
Given("^I have an account at Central EGA$", () -> {
- DockerClient dockerClient = utils.getDockerClient();
- String cegaUsersFolderPath = Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/cega/users";
- String name = UUID.randomUUID().toString();
- String dataFolderName = context.getDataFolder().getName();
- CreateContainerResponse createContainerResponse = dockerClient.
- createContainerCmd("nbis/ega:worker").
- withName(name).
- withCmd("sleep", "1000").
- withBinds(new Bind(cegaUsersFolderPath, new Volume("/" + dataFolderName))).
- exec();
- dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
- try {
- Container tempWorker = utils.findContainer("nbis/ega:worker", name);
- double password = Math.random();
- String user = context.getUser();
- utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
- utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
- String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
- File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
- FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
- } catch (IOException | InterruptedException e) {
- log.error(e.getMessage(), e);
- } finally {
- dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
+ for (String instance : context.getInstances()) {
+ DockerClient dockerClient = utils.getDockerClient();
+ String cegaUsersFolderPath = utils.getPrivateFolderPath() + "/cega/users/" + instance;
+ String name = UUID.randomUUID().toString();
+ String dataFolderName = context.getDataFolder().getName();
+ CreateContainerResponse createContainerResponse = dockerClient.
+ createContainerCmd("nbisweden/ega-worker").
+ withName(name).
+ withCmd("sleep", "1000").
+ withBinds(new Bind(cegaUsersFolderPath, new Volume("/" + dataFolderName))).
+ exec();
+ dockerClient.startContainerCmd(createContainerResponse.getId()).exec();
+ try {
+ Container tempWorker = utils.findContainer("nbisweden/ega-worker", name);
+ double password = Math.random();
+ String user = context.getUser();
+ String opensslCommand = utils.readTraceProperty(instance, "OPENSSL exec");
+ utils.executeWithinContainer(tempWorker, String.format("%s genrsa -out /%s/%s.sec -passout pass:%f 2048", opensslCommand, dataFolderName, user, password).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("%s rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", opensslCommand, dataFolderName, user, password, dataFolderName, user).split(" "));
+ String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
+ File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
+ FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ } finally {
+ dockerClient.removeContainerCmd(createContainerResponse.getId()).withForce(true).exec();
+ }
}
});
+ Given("^I want to work with instance \"([^\"]*)\"$", context::setTargetInstance);
+
Given("^I have correct private key$",
- () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", context.getUser()))));
+ () -> {
+ try {
+ File privateKey = new File(String.format("%s/cega/users/%s/%s.sec", utils.getPrivateFolderPath(), context.getTargetInstance(), context.getUser()));
+ Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
+ context.setPrivateKey(privateKey);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
Given("^I have incorrect private key$",
- () -> context.setPrivateKey(new File(Paths.get("").toAbsolutePath().getParent().toString() + String.format("/docker/bootstrap/private/cega/users/%s.sec", "john"))));
+ () -> context.setPrivateKey(new File(String.format("%s/cega/users/%s.sec", utils.getPrivateFolderPath(), "john"))));
When("^my account expires$", () -> {
connect(context);
disconnect(context);
try {
Thread.sleep(1000);
- utils.executeDBQuery(String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
+ utils.executeDBQuery(context.getTargetInstance(),
+ String.format("update users set expiration = '1 second' where elixir_id = '%s'", context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
}
@@ -84,7 +100,7 @@ public Authentication(Context context) {
When("^inbox is not created for me$", () -> {
try {
disconnect(context);
- utils.removeUserFromInbox(context.getUser());
+ utils.removeUserFromInbox(context.getTargetInstance(), context.getUser());
connect(context);
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
@@ -93,7 +109,7 @@ public Authentication(Context context) {
Then("^I am in the local database$", () -> {
try {
- Assert.assertTrue(utils.isUserExistInDB(context.getUser()));
+ Assert.assertTrue(utils.isUserExistInDB(context.getTargetInstance(), context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -102,7 +118,7 @@ public Authentication(Context context) {
Then("^I am not in the local database$", () -> {
try {
- Assert.assertFalse(utils.isUserExistInDB(context.getUser()));
+ Assert.assertFalse(utils.isUserExistInDB(context.getTargetInstance(), context.getUser()));
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -121,7 +137,6 @@ private void connect(Context context) {
ssh.addHostKeyVerifier(new PromiscuousVerifier());
ssh.connect("localhost", 2222);
File privateKey = context.getPrivateKey();
- Files.setPosixFilePermissions(privateKey.toPath(), Collections.singleton(PosixFilePermission.OWNER_READ));
ssh.authPublickey(context.getUser(), privateKey.getPath());
context.setSsh(ssh);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
index 3560a8d7..4d839506 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -18,8 +18,10 @@ public Ingestion(Context context) {
Given("^I have CEGA username and password$", () -> {
try {
- context.setCegaMQUser(utils.readTraceProperty("CEGA_MQ_USER"));
- context.setCegaMQPassword(utils.readTraceProperty("CEGA_MQ_PASSWORD"));
+ context.setCegaMQUser(utils.readTraceProperty(context.getTargetInstance(), "CEGA_MQ_USER"));
+ context.setCegaMQPassword(utils.readTraceProperty(context.getTargetInstance(), "CEGA_MQ_PASSWORD"));
+ context.setCegaMQVHost(context.getTargetInstance());
+ context.setRoutingKey(context.getTargetInstance());
} catch (IOException e) {
log.error(e.getMessage(), e);
Assert.fail(e.getMessage());
@@ -29,11 +31,12 @@ public Ingestion(Context context) {
When("^I ingest file from the LocalEGA inbox$", () -> {
try {
File encryptedFile = context.getEncryptedFile();
- utils.executeWithinContainer(utils.findContainer("nbis/ega:cega_mq", "cega_mq"),
- String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s --unenc %s --enc %s",
+ utils.executeWithinContainer(utils.findContainer("nbisweden/ega-cega_mq", "cega_mq"),
+ String.format("publish --connection amqp://%s:%s@localhost:5672/%s %s %s %s --unenc %s --enc %s",
context.getCegaMQUser(),
context.getCegaMQPassword(),
- utils.readTraceProperty("CEGA_MQ_VHOST"),
+ context.getCegaMQVHost(),
+ context.getRoutingKey(),
context.getUser(),
encryptedFile.getName(),
utils.calculateMD5(context.getRawFile()),
@@ -47,9 +50,10 @@ public Ingestion(Context context) {
Then("^the file is ingested successfully$", () -> {
try {
- String output = utils.executeDBQuery(String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName()));
+ String output = utils.executeDBQuery(context.getTargetInstance(),
+ String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName()));
String vaultFileName = output.split(System.getProperty("line.separator"))[2];
- String cat = utils.executeWithinContainer(utils.findContainer("nbis/ega:common", "ega_vault"), "cat", vaultFileName.trim());
+ String cat = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-common", "ega_vault"), "cat", vaultFileName.trim());
Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index dcae27d6..21bd51d4 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -31,12 +31,14 @@ public Uploading(Context context) {
Volume gpgVolume = new Volume("/root/.gnupg");
CreateContainerResponse createContainerResponse = null;
try {
+ String targetInstance = context.getTargetInstance();
+ String gpgCommand = utils.readTraceProperty(targetInstance, "GPG exec");
createContainerResponse = dockerClient.
- createContainerCmd("nbis/ega:worker").
+ createContainerCmd("nbisweden/ega-worker").
withVolumes(dataVolume, gpgVolume).
withBinds(new Bind(Paths.get(dataFolderName).toAbsolutePath().toString(), dataVolume),
- new Bind(Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private/gpg", gpgVolume, AccessMode.ro)).
- withCmd(utils.readTraceProperty("GPG exec"), "-r", utils.readTraceProperty("GPG_EMAIL"), "-e", "-o", String.format("/%s/%s.enc", dataFolderName, rawFile.getName()), String.format("/%s/%s", dataFolderName, rawFile.getName())).
+ new Bind(String.format("%s/%s/gpg", utils.getPrivateFolderPath(), targetInstance), gpgVolume, AccessMode.ro)).
+ withCmd(gpgCommand, "-r", utils.readTraceProperty(targetInstance, "GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
exec();
} catch (IOException e) {
log.error(e.getMessage(), e);
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index 166d0211..78f416a0 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -2,35 +2,45 @@ Feature: Authentication
As a user I want to be able to authenticate against LocalEGA inbox
Scenario: User population in LocalEGA DB from Central EGA
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then I am in the local database
Scenario: User doesn't exist in Central EGA, but tries to authenticate against LocalEGA inbox
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
+ And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
Scenario: User exists in Central EGA, but uses incorrect private key for authentication
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have incorrect private key
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
Scenario: User exists in Central EGA, but his account has expired
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
When my account expires
Then I am not in the local database
Scenario: User exists in Central EGA and uses correct private key for authentication
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then I'm logged in successfully
\ No newline at end of file
diff --git a/tests/src/test/resources/cucumber/features/ingestion.feature b/tests/src/test/resources/cucumber/features/ingestion.feature
index 65dfb331..7cdeb8a9 100644
--- a/tests/src/test/resources/cucumber/features/ingestion.feature
+++ b/tests/src/test/resources/cucumber/features/ingestion.feature
@@ -2,8 +2,10 @@ Feature: Ingestion
As a user I want to be able to ingest files from the LocalEGA inbox
Scenario: Ingest files from the LocalEGA inbox
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
diff --git a/tests/src/test/resources/cucumber/features/uploading.feature b/tests/src/test/resources/cucumber/features/uploading.feature
index 9adf5c3c..f7bf08b1 100644
--- a/tests/src/test/resources/cucumber/features/uploading.feature
+++ b/tests/src/test/resources/cucumber/features/uploading.feature
@@ -2,8 +2,10 @@ Feature: Uploading
As a user I want to be able to upload files to the LocalEGA inbox
Scenario: Upload files to the LocalEGA inbox
- Given I am a user
+ Given I am a user of LocalEGA instances:
+ | swe1 |
And I have an account at Central EGA
+ And I want to work with instance "swe1"
And I have correct private key
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
From 3a3506d5f626b09b0ec45d0718074c897cc5f259 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Fri, 10 Nov 2017 13:32:03 +0100
Subject: [PATCH 115/528] Add inbox removal test.
---
.../lega/cucumber/steps/Authentication.java | 14 ++++--
.../cucumber/features/authentication.feature | 47 ++++++++++++-------
2 files changed, 40 insertions(+), 21 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 0b4cad36..59bdf4b2 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -81,6 +81,14 @@ public Authentication(Context context) {
Given("^I have incorrect private key$",
() -> context.setPrivateKey(new File(String.format("%s/cega/users/%s.sec", utils.getPrivateFolderPath(), "john"))));
+ Given("^Inbox is deleted for my user$", () -> {
+ try {
+ utils.removeUserFromInbox(context.getTargetInstance(), context.getUser());
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
+ });
+
When("^my account expires$", () -> {
connect(context);
disconnect(context);
@@ -93,9 +101,9 @@ public Authentication(Context context) {
}
});
- When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> {
- connect(context);
- });
+ When("^I connect to the LocalEGA inbox via SFTP using private key$", () -> connect(context));
+
+ When("^I disconnect from the LocalEGA inbox$", () -> disconnect(context));
When("^inbox is not created for me$", () -> {
try {
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index 78f416a0..d4808e1f 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -1,45 +1,56 @@
Feature: Authentication
As a user I want to be able to authenticate against LocalEGA inbox
- Scenario: User population in LocalEGA DB from Central EGA
+ Background:
Given I am a user of LocalEGA instances:
| swe1 |
- And I have an account at Central EGA
+
+ Scenario: User population in LocalEGA DB from Central EGA
+ Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
Then I am in the local database
Scenario: User doesn't exist in Central EGA, but tries to authenticate against LocalEGA inbox
- Given I am a user of LocalEGA instances:
- | swe1 |
+ Given I want to work with instance "swe1"
+ And I have correct private key
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
+ Scenario: User exists in Central EGA, but his account has expired
+ Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have correct private key
+ When my account expires
+ Then I am not in the local database
+
+ Scenario: User exists in Central EGA and tries to connect to LocalEGA, but the inbox was not created for him
+ Given I have an account at Central EGA
+ And I want to work with instance "swe1"
+ And I have correct private key
+ And I connect to the LocalEGA inbox via SFTP using private key
+ And I disconnect from the LocalEGA inbox
+ And Inbox is deleted for my user
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
Scenario: User exists in Central EGA, but uses incorrect private key for authentication
- Given I am a user of LocalEGA instances:
- | swe1 |
- And I have an account at Central EGA
+ Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have incorrect private key
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
- Scenario: User exists in Central EGA, but his account has expired
- Given I am a user of LocalEGA instances:
- | swe1 |
- And I have an account at Central EGA
- And I want to work with instance "swe1"
+ Scenario: User exists in Central EGA and uses correct private key for authentication, but the wrong instance
+ Given I have an account at Central EGA
+ And I want to work with instance "fin1"
And I have correct private key
- When my account expires
- Then I am not in the local database
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
- Scenario: User exists in Central EGA and uses correct private key for authentication
- Given I am a user of LocalEGA instances:
- | swe1 |
- And I have an account at Central EGA
+ Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance
+ Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
From 238e27a10c91e19d0673d51a28d956e295f7e8c6 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Fri, 10 Nov 2017 13:55:50 +0100
Subject: [PATCH 116/528] Add "database down" test.
---
tests/src/test/java/se/nbis/lega/cucumber/Utils.java | 2 +-
.../se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java | 9 +++++++++
.../java/se/nbis/lega/cucumber/steps/Authentication.java | 5 +++++
.../resources/cucumber/features/authentication.feature | 8 ++++++++
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index 2d016ebf..b66a2f23 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -170,7 +170,7 @@ public String readTraceProperty(String instance, String property) throws IOExcep
* @return Docker container.
*/
public Container findContainer(String imageName, String containerName) {
- return dockerClient.listContainersCmd().exec().
+ return dockerClient.listContainersCmd().withShowAll(true).exec().
stream().
filter(c -> c.getImage().equals(imageName)).
filter(c -> ArrayUtils.contains(c.getNames(), "/" + containerName)).
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index c68e4631..b5a40ab6 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -1,5 +1,7 @@
package se.nbis.lega.cucumber.hooks;
+import com.github.dockerjava.api.exception.NotModifiedException;
+import com.github.dockerjava.api.model.Container;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java8.En;
@@ -33,6 +35,13 @@ public void setUp() throws IOException {
@After
public void tearDown() throws IOException, InterruptedException {
Utils utils = context.getUtils();
+
+ try { // bring DB back in case it's gone down
+ Container dbContainer = utils.findContainer("nbisweden/ega-db", "ega_db_" + context.getTargetInstance());
+ utils.getDockerClient().startContainerCmd(dbContainer.getId()).exec();
+ } catch (NotModifiedException e) {
+ }
+
FileUtils.deleteDirectory(context.getDataFolder());
String targetInstance = context.getTargetInstance();
File cegaUsersFolder = new File(utils.getPrivateFolderPath() + "/cega/users/" + targetInstance);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 59bdf4b2..9f6eddec 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -89,6 +89,11 @@ public Authentication(Context context) {
}
});
+ Given("^database is down$", () -> {
+ Container dbContainer = utils.findContainer("nbisweden/ega-db", "ega_db_" + context.getTargetInstance());
+ utils.getDockerClient().stopContainerCmd(dbContainer.getId()).exec();
+ });
+
When("^my account expires$", () -> {
connect(context);
disconnect(context);
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index d4808e1f..6338edd8 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -49,6 +49,14 @@ Feature: Authentication
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
+ Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance, but database is down
+ Given I have an account at Central EGA
+ And I want to work with instance "swe1"
+ And I have correct private key
+ And database is down
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
+
Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance
Given I have an account at Central EGA
And I want to work with instance "swe1"
From a1fd5cf5ba3b73d4f00436131ae7d9bc0f4b33f3 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Mon, 13 Nov 2017 13:33:58 +0100
Subject: [PATCH 117/528] Update tests according to recent multi-ega changes.
---
docker/bootstrap/lib/instance.sh | 3 ++-
.../test/java/se/nbis/lega/cucumber/Utils.java | 4 ++--
.../lega/cucumber/hooks/BeforeAfterHooks.java | 18 +++++++++++++++---
.../lega/cucumber/steps/Authentication.java | 10 +++++-----
.../se/nbis/lega/cucumber/steps/Ingestion.java | 6 +++---
.../se/nbis/lega/cucumber/steps/Uploading.java | 5 ++---
.../cucumber/features/authentication.feature | 16 ++++++++--------
.../cucumber/features/uploading.feature | 2 +-
8 files changed, 38 insertions(+), 26 deletions(-)
diff --git a/docker/bootstrap/lib/instance.sh b/docker/bootstrap/lib/instance.sh
index c08f5f78..1a8711b1 100755
--- a/docker/bootstrap/lib/instance.sh
+++ b/docker/bootstrap/lib/instance.sh
@@ -177,8 +177,9 @@ DB_TRY = ${DB_TRY}
#
LEGA_GREETINGS = ${LEGA_GREETINGS}
#
-CEGA_REST_PASSWORD = ${CEGA_REST_PASSWORD}
+CEGA_MQ_USER = cega_${INSTANCE}
CEGA_MQ_PASSWORD = ${CEGA_MQ_PASSWORD}
+CEGA_REST_PASSWORD = ${CEGA_REST_PASSWORD}
#
DOCKER_INBOX_PORT = ${DOCKER_INBOX_PORT}
EOF
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index b66a2f23..1e4e34bf 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -41,7 +41,7 @@ public Utils() {
* @return Absolute path or a private folder.
*/
public String getPrivateFolderPath() {
- return Paths.get("").toAbsolutePath().getParent().toString() + "/docker/bootstrap/private";
+ return Paths.get("").toAbsolutePath().getParent().toString() + "/docker/private";
}
/**
@@ -154,7 +154,7 @@ public void spawnWorkerAndExecute(String instance, String from, String to, Strin
* @throws IOException In case it's not possible to read trace file.
*/
public String readTraceProperty(String instance, String property) throws IOException {
- File trace = new File(getPrivateFolderPath() + "/.trace." + instance);
+ File trace = new File(String.format("%s/%s/.trace", getPrivateFolderPath(), instance));
return FileUtils.readLines(trace, Charset.defaultCharset()).
stream().
filter(l -> l.startsWith(property)).
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index b5a40ab6..3bee85e5 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -5,7 +5,9 @@
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java8.En;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
import se.nbis.lega.cucumber.Context;
import se.nbis.lega.cucumber.Utils;
@@ -14,6 +16,7 @@
import java.nio.charset.Charset;
import java.util.Arrays;
+@Slf4j
public class BeforeAfterHooks implements En {
private Context context;
@@ -36,14 +39,23 @@ public void setUp() throws IOException {
public void tearDown() throws IOException, InterruptedException {
Utils utils = context.getUtils();
- try { // bring DB back in case it's gone down
- Container dbContainer = utils.findContainer("nbisweden/ega-db", "ega_db_" + context.getTargetInstance());
+ // bring DB back in case it's down
+ String targetInstance = context.getTargetInstance();
+ try {
+ Container dbContainer = utils.findContainer("nbisweden/ega-db", "ega_db_" + targetInstance);
utils.getDockerClient().startContainerCmd(dbContainer.getId()).exec();
+ for (int i = 0; i < Integer.parseInt(utils.readTraceProperty(targetInstance, "DB_TRY")); i++) {
+ String testQueryResult = utils.executeDBQuery(targetInstance, "select * from users;");
+ if (StringUtils.isNotEmpty(testQueryResult)) {
+ break;
+ }
+ log.info("DB is down, trying to bring it up. Attempt: " + i);
+ Thread.sleep(1000);
+ }
} catch (NotModifiedException e) {
}
FileUtils.deleteDirectory(context.getDataFolder());
- String targetInstance = context.getTargetInstance();
File cegaUsersFolder = new File(utils.getPrivateFolderPath() + "/cega/users/" + targetInstance);
String user = context.getUser();
Arrays.stream(cegaUsersFolder.listFiles((dir, name) -> name.startsWith(user))).forEach(File::delete);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 9f6eddec..d389a0be 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -51,9 +51,8 @@ public Authentication(Context context) {
Container tempWorker = utils.findContainer("nbisweden/ega-worker", name);
double password = Math.random();
String user = context.getUser();
- String opensslCommand = utils.readTraceProperty(instance, "OPENSSL exec");
- utils.executeWithinContainer(tempWorker, String.format("%s genrsa -out /%s/%s.sec -passout pass:%f 2048", opensslCommand, dataFolderName, user, password).split(" "));
- utils.executeWithinContainer(tempWorker, String.format("%s rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", opensslCommand, dataFolderName, user, password, dataFolderName, user).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("openssl genrsa -out /%s/%s.sec -passout pass:%f 2048", dataFolderName, user, password).split(" "));
+ utils.executeWithinContainer(tempWorker, String.format("openssl rsa -in /%s/%s.sec -passin pass:%f -pubout -out /%s/%s.pub", dataFolderName, user, password, dataFolderName, user).split(" "));
String publicKey = utils.executeWithinContainer(tempWorker, String.format("ssh-keygen -i -mPKCS8 -f /%s/%s.pub", dataFolderName, user).split(" "));
File userYML = new File(String.format(cegaUsersFolderPath + "/%s.yml", user));
FileUtils.writeLines(userYML, Arrays.asList("---", "pubkey: " + publicKey));
@@ -148,7 +147,8 @@ private void connect(Context context) {
try {
SSHClient ssh = new SSHClient();
ssh.addHostKeyVerifier(new PromiscuousVerifier());
- ssh.connect("localhost", 2222);
+ ssh.connect("localhost",
+ Integer.parseInt(context.getUtils().readTraceProperty(context.getTargetInstance(), "DOCKER_INBOX_PORT")));
File privateKey = context.getPrivateKey();
ssh.authPublickey(context.getUser(), privateKey.getPath());
@@ -170,4 +170,4 @@ private void disconnect(Context context) {
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
index 4d839506..5736ec0a 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Ingestion.java
@@ -16,7 +16,7 @@ public class Ingestion implements En {
public Ingestion(Context context) {
Utils utils = context.getUtils();
- Given("^I have CEGA username and password$", () -> {
+ Given("^I have CEGA MQ username and password$", () -> {
try {
context.setCegaMQUser(utils.readTraceProperty(context.getTargetInstance(), "CEGA_MQ_USER"));
context.setCegaMQPassword(utils.readTraceProperty(context.getTargetInstance(), "CEGA_MQ_PASSWORD"));
@@ -53,7 +53,7 @@ public Ingestion(Context context) {
String output = utils.executeDBQuery(context.getTargetInstance(),
String.format("select stable_id from files where filename = '%s'", context.getEncryptedFile().getName()));
String vaultFileName = output.split(System.getProperty("line.separator"))[2];
- String cat = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-common", "ega_vault"), "cat", vaultFileName.trim());
+ String cat = utils.executeWithinContainer(utils.findContainer("nbisweden/ega-common", "ega_vault_" + context.getTargetInstance()), "cat", vaultFileName.trim());
Assertions.assertThat(cat).startsWith("bytearray(b'1')|256|8|b'CTR'");
} catch (IOException | InterruptedException e) {
log.error(e.getMessage(), e);
@@ -62,4 +62,4 @@ public Ingestion(Context context) {
});
}
-}
\ No newline at end of file
+}
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
index 21bd51d4..9d3f0edb 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Uploading.java
@@ -32,13 +32,12 @@ public Uploading(Context context) {
CreateContainerResponse createContainerResponse = null;
try {
String targetInstance = context.getTargetInstance();
- String gpgCommand = utils.readTraceProperty(targetInstance, "GPG exec");
createContainerResponse = dockerClient.
createContainerCmd("nbisweden/ega-worker").
withVolumes(dataVolume, gpgVolume).
withBinds(new Bind(Paths.get(dataFolderName).toAbsolutePath().toString(), dataVolume),
new Bind(String.format("%s/%s/gpg", utils.getPrivateFolderPath(), targetInstance), gpgVolume, AccessMode.ro)).
- withCmd(gpgCommand, "-r", utils.readTraceProperty(targetInstance, "GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
+ withCmd("gpg2", "-r", utils.readTraceProperty(targetInstance, "GPG_EMAIL"), "-e", "-o", "/data/" + rawFile.getName() + ".enc", "/data/" + rawFile.getName()).
exec();
} catch (IOException e) {
log.error(e.getMessage(), e);
@@ -77,4 +76,4 @@ public Uploading(Context context) {
});
}
-}
\ No newline at end of file
+}
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index 6338edd8..def77bae 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -49,17 +49,17 @@ Feature: Authentication
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
- Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance, but database is down
- Given I have an account at Central EGA
- And I want to work with instance "swe1"
- And I have correct private key
- And database is down
- When I connect to the LocalEGA inbox via SFTP using private key
- Then authentication fails
+# Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance, but database is down
+# Given I have an account at Central EGA
+# And I want to work with instance "swe1"
+# And I have correct private key
+# And database is down
+# When I connect to the LocalEGA inbox via SFTP using private key
+# Then authentication fails
Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance
Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have correct private key
When I connect to the LocalEGA inbox via SFTP using private key
- Then I'm logged in successfully
\ No newline at end of file
+ Then I'm logged in successfully
diff --git a/tests/src/test/resources/cucumber/features/uploading.feature b/tests/src/test/resources/cucumber/features/uploading.feature
index f7bf08b1..6f3780d5 100644
--- a/tests/src/test/resources/cucumber/features/uploading.feature
+++ b/tests/src/test/resources/cucumber/features/uploading.feature
@@ -10,4 +10,4 @@ Feature: Uploading
And I connect to the LocalEGA inbox via SFTP using private key
And I have an encrypted file
When I upload encrypted file to the LocalEGA inbox via SFTP
- Then the file is uploaded successfully
\ No newline at end of file
+ Then the file is uploaded successfully
From 95e72cbe9236d351c744377cc6c79924f1c66899 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 14 Nov 2017 15:47:54 +0100
Subject: [PATCH 118/528] Putting the - back when removing the :latest tag
---
docker/images/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker/images/Makefile b/docker/images/Makefile
index d0577b65..ec7563bc 100644
--- a/docker/images/Makefile
+++ b/docker/images/Makefile
@@ -19,7 +19,7 @@ worker: common
cega_users: common
$(EGA_IMAGES):
- docker rmi $(TARGET)-$@:latest
+ -docker rmi $(TARGET)-$@:latest
docker pull $(TARGET)-$@:latest
docker build --cache-from $(TARGET)-$@:latest --tag $(TARGET)-$@:$(TAG) $@
docker tag $(TARGET)-$@:$(TAG) $(TARGET)-$@:latest
From 90d49aaf88a4591bc1752f043a36028c1e26dbd2 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Thu, 16 Nov 2017 15:03:19 +0100
Subject: [PATCH 119/528] Fix "database not available" user authentication
test.
---
.../java/se/nbis/lega/cucumber/Utils.java | 4 +++-
.../lega/cucumber/hooks/BeforeAfterHooks.java | 24 +++++--------------
.../lega/cucumber/steps/Authentication.java | 10 +++++---
.../cucumber/features/authentication.feature | 14 +++++------
4 files changed, 23 insertions(+), 29 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
index 1e4e34bf..72664973 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/Utils.java
@@ -159,7 +159,9 @@ public String readTraceProperty(String instance, String property) throws IOExcep
stream().
filter(l -> l.startsWith(property)).
map(p -> p.split(" = ")[1]).
- findAny().orElse(null);
+ findAny().
+ orElseThrow(() -> new RuntimeException(String.format("Property %s not found for instance %s", property, instance))).
+ trim();
}
/**
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
index 3bee85e5..b67de0e1 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/hooks/BeforeAfterHooks.java
@@ -1,13 +1,10 @@
package se.nbis.lega.cucumber.hooks;
-import com.github.dockerjava.api.exception.NotModifiedException;
-import com.github.dockerjava.api.model.Container;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java8.En;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.StringUtils;
import se.nbis.lega.cucumber.Context;
import se.nbis.lega.cucumber.Utils;
@@ -25,6 +22,7 @@ public BeforeAfterHooks(Context context) {
this.context = context;
}
+ @SuppressWarnings("ResultOfMethodCallIgnored")
@Before
public void setUp() throws IOException {
File dataFolder = new File("data");
@@ -35,25 +33,15 @@ public void setUp() throws IOException {
context.setRawFile(rawFile);
}
+ @SuppressWarnings({"ConstantConditions", "ResultOfMethodCallIgnored"})
@After
public void tearDown() throws IOException, InterruptedException {
Utils utils = context.getUtils();
-
- // bring DB back in case it's down
String targetInstance = context.getTargetInstance();
- try {
- Container dbContainer = utils.findContainer("nbisweden/ega-db", "ega_db_" + targetInstance);
- utils.getDockerClient().startContainerCmd(dbContainer.getId()).exec();
- for (int i = 0; i < Integer.parseInt(utils.readTraceProperty(targetInstance, "DB_TRY")); i++) {
- String testQueryResult = utils.executeDBQuery(targetInstance, "select * from users;");
- if (StringUtils.isNotEmpty(testQueryResult)) {
- break;
- }
- log.info("DB is down, trying to bring it up. Attempt: " + i);
- Thread.sleep(1000);
- }
- } catch (NotModifiedException e) {
- }
+
+ // fix database connectivity
+ utils.executeWithinContainer(utils.findContainer("nbisweden/ega-inbox", "ega_inbox_" + context.getTargetInstance()),
+ "sed -i s/dbname=wrong/dbname=lega/g /etc/ega/auth.conf".split(" "));
FileUtils.deleteDirectory(context.getDataFolder());
File cegaUsersFolder = new File(utils.getPrivateFolderPath() + "/cega/users/" + targetInstance);
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index d389a0be..8bdc1fa9 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -88,9 +88,13 @@ public Authentication(Context context) {
}
});
- Given("^database is down$", () -> {
- Container dbContainer = utils.findContainer("nbisweden/ega-db", "ega_db_" + context.getTargetInstance());
- utils.getDockerClient().stopContainerCmd(dbContainer.getId()).exec();
+ Given("^I break the database connectivity$", () -> {
+ try {
+ utils.executeWithinContainer(utils.findContainer("nbisweden/ega-inbox", "ega_inbox_" + context.getTargetInstance()),
+ "sed -i s/dbname=lega/dbname=wrong/g /etc/ega/auth.conf".split(" "));
+ } catch (IOException | InterruptedException e) {
+ log.error(e.getMessage(), e);
+ }
});
When("^my account expires$", () -> {
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index def77bae..fff135da 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -49,13 +49,13 @@ Feature: Authentication
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
-# Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance, but database is down
-# Given I have an account at Central EGA
-# And I want to work with instance "swe1"
-# And I have correct private key
-# And database is down
-# When I connect to the LocalEGA inbox via SFTP using private key
-# Then authentication fails
+ Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance, but database is down
+ Given I have an account at Central EGA
+ And I want to work with instance "swe1"
+ And I have correct private key
+ And I break the database connectivity
+ When I connect to the LocalEGA inbox via SFTP using private key
+ Then authentication fails
Scenario: User exists in Central EGA and uses correct private key for authentication for the correct instance
Given I have an account at Central EGA
From 89bbf2c43fee204a0a86af99e45845f965923dfe Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Thu, 16 Nov 2017 15:14:00 +0100
Subject: [PATCH 120/528] Fix scenario of DB connectivity test.
---
.../test/java/se/nbis/lega/cucumber/steps/Authentication.java | 2 +-
.../src/test/resources/cucumber/features/authentication.feature | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
index 8bdc1fa9..a8d859ea 100644
--- a/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
+++ b/tests/src/test/java/se/nbis/lega/cucumber/steps/Authentication.java
@@ -88,7 +88,7 @@ public Authentication(Context context) {
}
});
- Given("^I break the database connectivity$", () -> {
+ Given("^the database connectivity is broken$", () -> {
try {
utils.executeWithinContainer(utils.findContainer("nbisweden/ega-inbox", "ega_inbox_" + context.getTargetInstance()),
"sed -i s/dbname=lega/dbname=wrong/g /etc/ega/auth.conf".split(" "));
diff --git a/tests/src/test/resources/cucumber/features/authentication.feature b/tests/src/test/resources/cucumber/features/authentication.feature
index fff135da..35e0d21d 100644
--- a/tests/src/test/resources/cucumber/features/authentication.feature
+++ b/tests/src/test/resources/cucumber/features/authentication.feature
@@ -53,7 +53,7 @@ Feature: Authentication
Given I have an account at Central EGA
And I want to work with instance "swe1"
And I have correct private key
- And I break the database connectivity
+ And the database connectivity is broken
When I connect to the LocalEGA inbox via SFTP using private key
Then authentication fails
From 9be4142efa2d9b57b89f0e34b1416c3f73011658 Mon Sep 17 00:00:00 2001
From: Dmytro Titov
Date: Thu, 23 Nov 2017 11:05:20 +0100
Subject: [PATCH 121/528] Change Slack channel
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 4522746f..9ecc5ae8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,4 +29,4 @@ after_success:
notifications:
email: false
slack:
- secure: HYV1cipL+SFw4YFILZ+/BIn5TIZmQ5Opfwb3cUN+W6OPGm2yAiv4yvvsF4Kk6dIwoFxDNu/mdRLIX5kYCpFcfoFUZdRGk65kMpeXOcs6CzhgY6xILSEbD66rseayBHbvQ4Gd0xNoe+fdI28q0tphMkan4AVDyQwmDZNpk/1QqBpIugiBWQXY3UBXnXU5Yu5jIVPycPH70qQiU1R5BOn/Uw/pyDk9c/pH57sfGmzAMVyzp7UgN/sIbZ9MhTJZ1Dd6IRUO/DZJY8Z4ZkeUp7Mh8LHoQJyfwGqKH2rBGbpulXau43dtif1MvfQrI0xy2SUadlGSbUMmTKDay2mJquwS/uj1S2SrNi42VAZ6+in+f2qFLw34ZiyZKnVUiUKGAwo5ueSjN6aoEM1WT0YutflUhVGzm4dUhXLInpo0r7VNbkR2iOQ3qbdN4OqPaxZL34vHjbVMZkIuundbd1QTrGSJVGZVMmAwRUPrZhKqyvyDelZM1fV9e8ez+CNnq3XDWcVAuHiNp/NEiLZ42vc7/bXyOk3UBotEiBPseEDQddlZmd/mr56uD2qFFdfkyvNsywAKDPnw2qiXlVjUONOIfS9CdwPlbF2xQ5fNCoLEg40KWMopAICC6vGSHbPs3tkRq3LT2OgosMyrfBNeES12lLHi5KNoWtzEPs8WotHwHY4R75U=
+ secure: eUyEWWvrFbzW+j+WKIOrHm7zeJ+6+o/WmI5cp1UYsOT9emxGE4kzW057cG9EV+sgKUdoYP1zSfCH0TLSOjY7otyqccqZH5WxDtiBSEXpkA8ID8jzQnX1VZWFn1vK+gWpER87VdLonVGt4db1lqE3Gm/uCbEqzrmfYjE1Hrk4PM8FfLQfD3+YBPUnWGSZKAPmdHAKh7IF9VQ6f1zaspijp/Sxa7Dk9F+Z4o2nsZ1woSyOVAwWLJhkvEafyEFfb/9tPMF1wtoXlLEzV1JDRzyjzbLGXQcpo6+Qx3+v7w6eRbriifOq2tByBfeI+RlWytwOgb+B/mfN0uFPbdg/Bgr//NMDrqwCnFQs7A2Dj287mQZI4YpRvh4Cneu3ReVGQKd9SJq28BliwXBBv3xyeFfGEbBOMNKb0VCsNjRuWITncf/qx3Vxn13VAYxcdA9EZpa1UzT6V94nlbLUq3twFKBJiDmpraYnI+JGFCZ32Xh8bySNqbEBe7TnqAG015c4pKKx++3IQJePfSPbRKzwWNAM5yG7RuVmud5fxfN+KdQz7vKfjOeaHKG4PScfhRT0zthtgmPG+m5eCprIbdFlacU3UyobLtxZd8wI9qJnGGvB3bHOsuaqpS2ymDWbd/n1aeryrcTkS/gPuwMvTs6S32pRf/orKqyLfnSZPeTcOevbzHw=
From 3b947c14f6aeaecf51b4da3024ba870d8e4153d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Fri, 24 Nov 2017 17:41:10 +0100
Subject: [PATCH 122/528] Moving entrypoints inside container images
---
docker/Makefile | 2 +-
docker/bootstrap/boot.sh | 1 -
docker/ega.yml | 29 ++++---------
docker/images/Makefile | 41 +++++++++++--------
docker/images/README.md | 14 ++++++-
docker/images/common/Dockerfile | 16 +++-----
docker/images/frontend/Dockerfile | 13 ++++++
.../frontend}/frontend.sh | 0
docker/images/inbox/Dockerfile | 14 ++++++-
.../inbox.sh => images/inbox/entrypoint.sh} | 10 +----
docker/images/keys/Dockerfile | 11 +++++
.../keys.sh => images/keys/entrypoint.sh} | 22 +---------
docker/images/keys/gpg-agent.conf | 11 +++++
docker/images/vault/Dockerfile | 17 ++++++++
.../vault.sh => images/vault/entrypoint.sh} | 3 --
docker/images/worker/Dockerfile | 17 +++++++-
docker/images/worker/Dockerfile.bootstrap | 15 +++++++
.../ingest.sh => images/worker/entrypoint.sh} | 3 --
src/setup.py | 2 +-
19 files changed, 150 insertions(+), 91 deletions(-)
create mode 100644 docker/images/frontend/Dockerfile
rename docker/{entrypoints => images/frontend}/frontend.sh (100%)
rename docker/{entrypoints/inbox.sh => images/inbox/entrypoint.sh} (94%)
create mode 100644 docker/images/keys/Dockerfile
rename docker/{entrypoints/keys.sh => images/keys/entrypoint.sh} (51%)
create mode 100644 docker/images/keys/gpg-agent.conf
create mode 100644 docker/images/vault/Dockerfile
rename docker/{entrypoints/vault.sh => images/vault/entrypoint.sh} (87%)
create mode 100644 docker/images/worker/Dockerfile.bootstrap
rename docker/{entrypoints/ingest.sh => images/worker/entrypoint.sh} (91%)
diff --git a/docker/Makefile b/docker/Makefile
index 7b34e7c6..60663aba 100644
--- a/docker/Makefile
+++ b/docker/Makefile
@@ -4,7 +4,7 @@
all: up
.env private:
- @docker run --rm -it --name ega_bootstrap -v ${PWD}:/ega nbisweden/ega-worker /ega/bootstrap/boot.sh
+ @docker run --rm -it -v ${PWD}:/ega nbisweden/ega-bootstrap
bootstrap: .env private
diff --git a/docker/bootstrap/boot.sh b/docker/bootstrap/boot.sh
index fb460fff..b4c6f20d 100755
--- a/docker/bootstrap/boot.sh
+++ b/docker/bootstrap/boot.sh
@@ -57,7 +57,6 @@ exec 2>${PRIVATE}/.err
cat > ${DOT_ENV} < or latest | Sets up a postgres database with appropriate tables |
| nbisweden/ega-mq | or latest | Sets up a RabbitMQ message broker with appropriate accounts, exchanges, queues and bindings |
-| nbisweden/ega-common | or latest | Image including python 3.6.1 |
| nbisweden/ega-inbox | or latest | SFTP server on top of `nbisweden/ega-common:latest` |
+| nbisweden/ega-common | or latest | Image including python 3.6.1 |
+| nbisweden/ega-fronted | or latest | Frontend server |
| nbisweden/ega-worker | or latest | Adding GnuPG 2.2.2 to `nbisweden/ega-common:latest` |
+| nbisweden/ega-keys | or latest | Key server, depends on `nbisweden/ega-worker:latest` |
+| nbisweden/ega-vault | or latest | Vault container |
| nbisweden/ega-monitors | or latest | Including rsyslog or logstash |
We also use 2 stubbing images in order to fake the necessary Central EGA components
diff --git a/docker/images/common/Dockerfile b/docker/images/common/Dockerfile
index 2ac5e811..e857e0ce 100644
--- a/docker/images/common/Dockerfile
+++ b/docker/images/common/Dockerfile
@@ -1,22 +1,16 @@
FROM centos:latest
LABEL maintainer "Frédéric Haziza, NBIS"
-RUN yum -y update && \
+RUN yum -y install https://centos7.iuscommunity.org/ius-release.rpm && \
+ yum -y update && \
yum -y install gcc git curl make bzip2 unzip \
openssl \
nss-tools nc nmap tcpdump lsof strace \
- bash-completion bash-completion-extras
-
-##################################
-# For Python 3.6
-##################################
-
-RUN yum -y install https://centos7.iuscommunity.org/ius-release.rpm
-RUN yum -y install gcc python36u python36u-pip
+ bash-completion bash-completion-extras \
+ python36u python36u-pip
RUN [[ -e /lib64/libpython3.6m.so ]] || ln -s /lib64/libpython3.6m.so.1.0 /lib64/libpython3.6m.so
-# And some extra ones, to speed up booting the VMs
RUN pip3.6 install --upgrade pip && \
- pip3.6 install PyYaml Markdown pika==0.11.0 aiohttp==2.2.5 pycryptodomex==3.4.5 aiopg==0.13.0 colorama==0.3.7 aiohttp-jinja2==0.13.0
+ pip3.6 install PyYaml Markdown pika aiohttp pycryptodomex aiopg colorama aiohttp-jinja2
diff --git a/docker/images/frontend/Dockerfile b/docker/images/frontend/Dockerfile
new file mode 100644
index 00000000..450ffedc
--- /dev/null
+++ b/docker/images/frontend/Dockerfile
@@ -0,0 +1,13 @@
+FROM nbisweden/ega-common:latest
+LABEL maintainer "Frédéric Haziza, NBIS"
+
+ARG checkout=dev
+
+RUN git clone https://github.com/NBISweden/LocalEGA /root/ega && \
+ cd /root/ega && \
+ git checkout ${checkout} && \
+ pip3.6 install ./src
+# cd src && \
+# python3.6 setup.py install
+
+ENTRYPOINT ["ega-frontend"]
diff --git a/docker/entrypoints/frontend.sh b/docker/images/frontend/frontend.sh
similarity index 100%
rename from docker/entrypoints/frontend.sh
rename to docker/images/frontend/frontend.sh
diff --git a/docker/images/inbox/Dockerfile b/docker/images/inbox/Dockerfile
index 058b32a5..cdca1a52 100644
--- a/docker/images/inbox/Dockerfile
+++ b/docker/images/inbox/Dockerfile
@@ -33,6 +33,18 @@ RUN cp /etc/nsswitch.conf /etc/nsswitch.conf.bak && \
COPY banner /ega/banner
COPY sshd_config /etc/ssh/sshd_config
+COPY entrypoint.sh /usr/local/bin/entrypoint.sh
+
+ARG checkout=dev
+
+RUN git clone https://github.com/NBISweden/LocalEGA /root/ega && \
+ cd /root/ega && \
+ git checkout ${checkout} && \
+ cd src/auth && \
+ make install clean && \
+ ldconfig -v
RUN useradd ega
-RUN /usr/sbin/rsyslogd
+VOLUME /ega/inbox
+ENTRYPOINT ["entrypoint.sh"]
+# CMD "swe1"
diff --git a/docker/entrypoints/inbox.sh b/docker/images/inbox/entrypoint.sh
similarity index 94%
rename from docker/entrypoints/inbox.sh
rename to docker/images/inbox/entrypoint.sh
index 8d73c0c0..86de7dbf 100755
--- a/docker/entrypoints/inbox.sh
+++ b/docker/images/inbox/entrypoint.sh
@@ -2,21 +2,13 @@
set -e
-db_instance=ega_db_$1
-
chown root:ega /ega/inbox
chmod 750 /ega/inbox
chmod g+s /ega/inbox # setgid bit
-cp -r /root/ega /root/run
-pushd /root/run/auth
-make install #clean
-ldconfig -v
-popd
-
+db_instance=ega_db_$1
EGA_DB_IP=$(getent hosts ${db_instance} | awk '{ print $1 }')
-mkdir -p /etc/ega
cat > /etc/ega/auth.conf < /root/.gnupg/gpg-agent.conf </dev/null; do sleep 1; done
echo "Waiting for Local Message Broker"
diff --git a/docker/images/worker/Dockerfile b/docker/images/worker/Dockerfile
index f14ac66a..a8eea9bd 100644
--- a/docker/images/worker/Dockerfile
+++ b/docker/images/worker/Dockerfile
@@ -6,8 +6,23 @@ RUN yum -y install vim-common zlib-devel bzip2-devel
RUN mkdir -p /var/src/ega
COPY rpmbuild/RPMS/x86_64/*.rpm /var/src/ega/
-
RUN rpm -i /var/src/ega/*.rpm && \
rm -rf /var/src/ega && \
echo "/usr/local/lib64" > /etc/ld.so.conf.d/gpg2.conf && \
ldconfig -v
+
+COPY entrypoint.sh /usr/local/bin/entrypoint.sh
+RUN chmod 755 /usr/local/bin/entrypoint.sh
+ENTRYPOINT ["entrypoint.sh"]
+# CMD swe1
+
+VOLUME /ega/inbox
+VOLUME /ega/staging
+
+ARG checkout=dev
+RUN git clone https://github.com/NBISweden/LocalEGA /root/ega && \
+ cd /root/ega && \
+ git checkout ${checkout} && \
+ pip3.6 install ./src
+# cd src && \
+# python3.6 setup.py install
diff --git a/docker/images/worker/Dockerfile.bootstrap b/docker/images/worker/Dockerfile.bootstrap
new file mode 100644
index 00000000..330ccaf2
--- /dev/null
+++ b/docker/images/worker/Dockerfile.bootstrap
@@ -0,0 +1,15 @@
+FROM nbisweden/ega-common:latest
+LABEL maintainer "Frédéric Haziza, NBIS"
+
+RUN yum -y install vim-common zlib-devel bzip2-devel
+
+RUN mkdir -p /var/src/ega
+
+COPY rpmbuild/RPMS/x86_64/*.rpm /var/src/ega/
+RUN rpm -i /var/src/ega/*.rpm && \
+ rm -rf /var/src/ega && \
+ echo "/usr/local/lib64" > /etc/ld.so.conf.d/gpg2.conf && \
+ ldconfig -v
+
+VOLUME /ega
+ENTRYPOINT ["/ega/bootstrap/boot.sh"]
diff --git a/docker/entrypoints/ingest.sh b/docker/images/worker/entrypoint.sh
similarity index 91%
rename from docker/entrypoints/ingest.sh
rename to docker/images/worker/entrypoint.sh
index 7ab74460..33889122 100755
--- a/docker/entrypoints/ingest.sh
+++ b/docker/images/worker/entrypoint.sh
@@ -2,9 +2,6 @@
set -e
-cp -r /root/ega /root/run
-pip3.6 install /root/run
-
# echo "Waiting for Keyserver"
until nc -4 --send-only ega_keys_$1 9010 /dev/null; do sleep 1; done
echo "Starting the socket forwarder"
diff --git a/src/setup.py b/src/setup.py
index 5b79e370..7761f0c1 100644
--- a/src/setup.py
+++ b/src/setup.py
@@ -36,7 +36,7 @@ def readme():
install_requires=[
'pika==0.11.0',
'aiohttp==2.2.5',
- 'pycryptodomex==3.4.5',
+ 'pycryptodomex==3.4.7',
'aiopg==0.13.0',
'colorama==0.3.7',
'aiohttp-jinja2==0.13.0',
From 7d400e4ee7850d898d2be500e03c9abc236265e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Fri, 24 Nov 2017 17:43:28 +0100
Subject: [PATCH 123/528] Changing the image creation for Travis
---
.travis.yml | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 9ecc5ae8..23bd8b20 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,8 +7,11 @@ services:
before_install:
- |
- cd docker
- make -C images -j 4
+ cd docker/images
+ make pull
+ make common
+ make -j 4 images
+ cd ..
make bootstrap
sudo chown -R $USER .
From 330376d46b540ed9ac0d0fe806ec005ce411e027 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Fri, 24 Nov 2017 18:48:14 +0100
Subject: [PATCH 124/528] Adding ENV variable to remove hard-coded values
---
docker/bootstrap/lib/instance.sh | 1 +
docker/ega.yml | 12 ++++++------
docker/images/Makefile | 4 ++--
docker/images/inbox/Dockerfile | 6 ++++--
docker/images/inbox/entrypoint.sh | 8 +++++---
docker/images/keys/Dockerfile | 2 +-
docker/images/keys/entrypoint.sh | 5 ++++-
docker/images/monitors/Dockerfile | 2 +-
docker/images/vault/Dockerfile | 1 +
docker/images/vault/entrypoint.sh | 5 ++++-
docker/images/worker/Dockerfile | 13 ++++++++-----
docker/images/worker/entrypoint.sh | 11 ++++++++---
12 files changed, 45 insertions(+), 25 deletions(-)
diff --git a/docker/bootstrap/lib/instance.sh b/docker/bootstrap/lib/instance.sh
index 1a8711b1..23a06624 100755
--- a/docker/bootstrap/lib/instance.sh
+++ b/docker/bootstrap/lib/instance.sh
@@ -119,6 +119,7 @@ EOF
echomsg "\t* Generating the docker-compose configuration files"
cat > ${PRIVATE}/${INSTANCE}/db.env <&2 && exit 1
+
chown root:ega /ega/inbox
chmod 750 /ega/inbox
chmod g+s /ega/inbox # setgid bit
-db_instance=ega_db_$1
-EGA_DB_IP=$(getent hosts ${db_instance} | awk '{ print $1 }')
+EGA_DB_IP=$(getent hosts ${DB_INSTANCE} | awk '{ print $1 }')
cat > /etc/ega/auth.conf <&2 && exit 1
+
GPG=/usr/local/bin/gpg2
GPG_AGENT=/usr/local/bin/gpg-agent
GPG_PRESET=/usr/local/libexec/gpg-preset-passphrase
@@ -19,7 +22,7 @@ ${GPG_PRESET} --preset -P $GPG_PASSPHRASE $KEYGRIP
unset GPG_PASSPHRASE
echo "Starting the gpg-agent proxy"
-ega-socket-proxy "0.0.0.0:$1" /root/.gnupg/S.gpg-agent --certfile /etc/ega/ssl.cert --keyfile /etc/ega/ssl.key &
+ega-socket-proxy "0.0.0.0:$KEYSERVER_PORT" /root/.gnupg/S.gpg-agent --certfile /etc/ega/ssl.cert --keyfile /etc/ega/ssl.key &
echo "Starting the key management server"
exec ega-keyserver --keys /etc/ega/keys.ini
diff --git a/docker/images/monitors/Dockerfile b/docker/images/monitors/Dockerfile
index 5c9a476d..abcbb9f1 100644
--- a/docker/images/monitors/Dockerfile
+++ b/docker/images/monitors/Dockerfile
@@ -7,4 +7,4 @@ RUN yum -y update && \
rsyslog
COPY ega.conf /etc/rsyslog.d/ega.conf
-#ENTRYPOINT ["rsyslogd", "-n", "-f", "/etc/rsyslogd.conf"]
+CMD ["rsyslogd", "-n"]
diff --git a/docker/images/vault/Dockerfile b/docker/images/vault/Dockerfile
index 34678465..e0161c14 100644
--- a/docker/images/vault/Dockerfile
+++ b/docker/images/vault/Dockerfile
@@ -13,5 +13,6 @@ RUN git clone https://github.com/NBISweden/LocalEGA /root/ega && \
# cd src && \
# python3.6 setup.py install
+ENV MQ_INSTANCE=
ENTRYPOINT ["entrypoint.sh"]
# CMD swe1
diff --git a/docker/images/vault/entrypoint.sh b/docker/images/vault/entrypoint.sh
index cfc54979..10393b3a 100755
--- a/docker/images/vault/entrypoint.sh
+++ b/docker/images/vault/entrypoint.sh
@@ -2,10 +2,13 @@
set -e
+# MQ_INSTANCE env must be defined
+[[ -z "$MQ_INSTANCE" ]] && echo 'Environment MQ_INSTANCE is empty' 1>&2 && exit 1
+
echo "Waiting for Central Message Broker"
until nc -4 --send-only cega_mq 5672 /dev/null; do sleep 1; done
echo "Waiting for Local Message Broker"
-until nc -4 --send-only ega_mq_$1 5672 /dev/null; do sleep 1; done
+until nc -4 --send-only ${MQ_INSTANCE} 5672 /dev/null; do sleep 1; done
echo "Starting the verifier"
ega-verify &
diff --git a/docker/images/worker/Dockerfile b/docker/images/worker/Dockerfile
index a8eea9bd..afd2d289 100644
--- a/docker/images/worker/Dockerfile
+++ b/docker/images/worker/Dockerfile
@@ -11,11 +11,6 @@ RUN rpm -i /var/src/ega/*.rpm && \
echo "/usr/local/lib64" > /etc/ld.so.conf.d/gpg2.conf && \
ldconfig -v
-COPY entrypoint.sh /usr/local/bin/entrypoint.sh
-RUN chmod 755 /usr/local/bin/entrypoint.sh
-ENTRYPOINT ["entrypoint.sh"]
-# CMD swe1
-
VOLUME /ega/inbox
VOLUME /ega/staging
@@ -26,3 +21,11 @@ RUN git clone https://github.com/NBISweden/LocalEGA /root/ega && \
pip3.6 install ./src
# cd src && \
# python3.6 setup.py install
+
+COPY entrypoint.sh /usr/local/bin/entrypoint.sh
+RUN chmod 755 /usr/local/bin/entrypoint.sh
+
+ENV KEYSERVER_HOST=
+ENV KEYSERVER_PORT=
+ENV MQ_INSTANCE=
+ENTRYPOINT ["entrypoint.sh"]
diff --git a/docker/images/worker/entrypoint.sh b/docker/images/worker/entrypoint.sh
index 33889122..e6ff3918 100755
--- a/docker/images/worker/entrypoint.sh
+++ b/docker/images/worker/entrypoint.sh
@@ -2,15 +2,20 @@
set -e
+# MQ_INSTANCE, KEYSERVER_HOST and KEYSERVER_PORT env must be defined
+[[ -z "$MQ_INSTANCE" ]] && echo 'Environment MQ_INSTANCE is empty' 1>&2 && exit 1
+[[ -z "$KEYSERVER_HOST" ]] && echo 'Environment KEYSERVER_HOST is empty' 1>&2 && exit 1
+[[ -z "$KEYSERVER_PORT" ]] && echo 'Environment KEYSERVER_PORT is empty' 1>&2 && exit 1
+
# echo "Waiting for Keyserver"
-until nc -4 --send-only ega_keys_$1 9010 /dev/null; do sleep 1; done
+until nc -4 --send-only ${KEYSERVER_HOST} ${KEYSERVER_PORT} /dev/null; do sleep 1; done
echo "Starting the socket forwarder"
-ega-socket-forwarder /root/.gnupg/S.gpg-agent ega_keys_$1:9010 --certfile /etc/ega/ssl.cert &
+ega-socket-forwarder /root/.gnupg/S.gpg-agent ${KEYSERVER_HOST}:${KEYSERVER_PORT} --certfile /etc/ega/ssl.cert &
echo "Waiting for Central Message Broker"
until nc -4 --send-only cega_mq 5672 /dev/null; do sleep 1; done
echo "Waiting for Local Message Broker"
-until nc -4 --send-only ega_mq_$1 5672 /dev/null; do sleep 1; done
+until nc -4 --send-only ${MQ_INSTANCE} 5672 /dev/null; do sleep 1; done
echo "Starting the ingestion worker"
exec ega-ingest
From aadab5a4ebbcafe52388a70622d23d9a0b3ffe3e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 13 Sep 2017 12:25:54 +0200
Subject: [PATCH 125/528] Updating the workers, keys and merging the
no-connectors branch
---
terraform/README.md | 4 ----
.../instances/workers/cloud_init_keys.tpl | 7 +++++-
terraform/instances/workers/keys.sh | 20 +++++------------
terraform/instances/workers/preset.sh | 22 +++++++++----------
terraform/main.tf | 7 ------
5 files changed, 23 insertions(+), 37 deletions(-)
diff --git a/terraform/README.md b/terraform/README.md
index 73f064ec..b64d6915 100644
--- a/terraform/README.md
+++ b/terraform/README.md
@@ -38,10 +38,6 @@ So... network first:
terraform apply -target=module.db -target=module.mq -target=module.monitors
-...connecting to CentralEGA:
-
- terraform apply -target=module.connectors
-
...and the rest:
terraform apply
diff --git a/terraform/instances/workers/cloud_init_keys.tpl b/terraform/instances/workers/cloud_init_keys.tpl
index 3698ca20..157c437d 100644
--- a/terraform/instances/workers/cloud_init_keys.tpl
+++ b/terraform/instances/workers/cloud_init_keys.tpl
@@ -5,6 +5,11 @@ write_files:
owner: root:root
path: /root/boot.sh
permissions: '0700'
+ - encoding: b64
+ content: ${preset_script}
+ owner: root:root
+ path: /root/preset.sh
+ permissions: '0700'
- encoding: b64
content: ${hosts}
owner: root:root
@@ -38,7 +43,7 @@ write_files:
- encoding: b64
content: ${gpg_passphrase}
owner: ega:ega
- path: /tmp/gpg_passphrase
+ path: /root/gpg_passphrase
permissions: '0600'
runcmd:
diff --git a/terraform/instances/workers/keys.sh b/terraform/instances/workers/keys.sh
index 09a0b539..8b5ebf3d 100644
--- a/terraform/instances/workers/keys.sh
+++ b/terraform/instances/workers/keys.sh
@@ -98,6 +98,7 @@ Type=simple
ExecStart=/usr/local/bin/gpg-agent --supervised
ExecReload=/usr/local/bin/gpgconf --reload gpg-agent
#ExecStop=/usr/bin/pkill gpg-agent
+ExecPost=/root/preset.sh
StandardOutput=syslog
StandardError=syslog
@@ -153,22 +154,13 @@ disable-scdaemon
EOF
##############
+# echo "Enabling the ega user to linger"
+# loginctl enable-linger ega
+
echo "Starting the gpg-agent proxy"
systemctl start gpg-agent.socket gpg-agent-extra.socket gpg-agent.service ega-socket-proxy.service
systemctl enable gpg-agent.socket gpg-agent-extra.socket gpg-agent.service ega-socket-proxy.service
-##############
-#while gpg-connect-agent /bye; do sleep 2; done
-KEYGRIP=$(/usr/local/bin/gpg -k --with-keygrip ega@nbis.se | awk '/Keygrip/{print $3;exit;}')
-if [ ! -z "$KEYGRIP" ]; then
- echo 'Unlocking the GPG key'
- # This will use the standard socket. The proxy forwards to the extra socket.
- /usr/local/libexec/gpg-preset-passphrase --preset -P "$(cat /tmp/gpg_passphrase)" $KEYGRIP && \
- rm -f /tmp/gpg_passphrase
-else
- echo 'Skipping the GPG key preseting'
-fi
-
echo "Master GPG-agent ready"
-echo "Rebooting"
-systemctl reboot
+# echo "Rebooting"
+# systemctl reboot
diff --git a/terraform/instances/workers/preset.sh b/terraform/instances/workers/preset.sh
index ddf49ee4..ee0c2272 100644
--- a/terraform/instances/workers/preset.sh
+++ b/terraform/instances/workers/preset.sh
@@ -2,15 +2,15 @@
set -e
-# ##############
-# #while gpg-connect-agent /bye; do sleep 2; done
-# KEYGRIP=$(/usr/local/bin/gpg -k --with-keygrip ega@nbis.se | awk '/Keygrip/{print $3;exit;}')
-# if [ ! -z "$KEYGRIP" ]; then
-# echo 'Unlocking the GPG key'
-# /usr/local/libexec/gpg-preset-passphrase --preset -P "$(cat /tmp/gpg_passphrase)" $KEYGRIP && \
-# rm -f /tmp/gpg_passphrase
-# else
-# echo 'Skipping the GPG key preseting'
-# fi
+##############
+#while gpg-connect-agent /bye; do sleep 2; done
+KEYGRIP=$(/usr/local/bin/gpg -k --with-keygrip ega@nbis.se | awk '/Keygrip/{print $3;exit;}')
+if [ ! -z "$KEYGRIP" ]; then
+ echo 'Unlocking the GPG key'
+ # This will use the standard socket. The proxy forwards to the extra socket.
+ /usr/local/libexec/gpg-preset-passphrase --preset -P "$(cat /tmp/gpg_passphrase)" $KEYGRIP
+ # && rm -f /tmp/gpg_passphrase
+else
+ echo 'Skipping the GPG key preseting'
+fi
-# echo "Master GPG-agent ready"
diff --git a/terraform/main.tf b/terraform/main.tf
index d3bb9fd2..5cd3948a 100644
--- a/terraform/main.tf
+++ b/terraform/main.tf
@@ -59,13 +59,6 @@ module "mq" {
ega_key = "${openstack_compute_keypair_v2.ega_key.name}"
ega_net = "${module.network.net_id}"
}
-module "connectors" {
- source = "./instances/connectors"
- private_ip = "192.168.10.13"
- ega_key = "${openstack_compute_keypair_v2.ega_key.name}"
- ega_net = "${module.network.net_id}"
- lega_conf = "${base64encode("${file("${var.lega_conf}")}")}"
-}
module "inbox" {
source = "./instances/inbox"
volume_size = 600
From 373b2c98b2a6e9f0c2354bcbfe4c09f8092d3f80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Wed, 13 Sep 2017 12:41:38 +0200
Subject: [PATCH 126/528] ExecStartPost and not ExecPost
---
terraform/instances/workers/keys.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/terraform/instances/workers/keys.sh b/terraform/instances/workers/keys.sh
index 8b5ebf3d..00b03c3e 100644
--- a/terraform/instances/workers/keys.sh
+++ b/terraform/instances/workers/keys.sh
@@ -98,7 +98,7 @@ Type=simple
ExecStart=/usr/local/bin/gpg-agent --supervised
ExecReload=/usr/local/bin/gpgconf --reload gpg-agent
#ExecStop=/usr/bin/pkill gpg-agent
-ExecPost=/root/preset.sh
+ExecStartPost=/root/preset.sh
StandardOutput=syslog
StandardError=syslog
From 6f59ea2613ecbaef587bbd7d0b30e7d7d37536f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Thu, 14 Sep 2017 10:18:13 +0200
Subject: [PATCH 127/528] Starting them to test before enabling them
---
terraform/instances/workers/boot.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/terraform/instances/workers/boot.sh b/terraform/instances/workers/boot.sh
index 3994413b..7652849d 100644
--- a/terraform/instances/workers/boot.sh
+++ b/terraform/instances/workers/boot.sh
@@ -146,6 +146,7 @@ echo "Enabling the ega user to linger"
loginctl enable-linger ega
echo "Enabling services"
+systemctl start ega-worker.service ega-socket-forwarder.service ega-socket-forwarder.socket
systemctl enable ega-worker.service ega-socket-forwarder.service ega-socket-forwarder.socket
From 9551d17ddff6ae87df9e042fde6808102be7ce8f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 14 Nov 2017 21:24:48 +0100
Subject: [PATCH 128/528] Adding a bootstrap for Terraform
---
terraform/.gitignore | 4 +-
terraform/bootstrap/boot.sh | 120 +++++++++++++++
terraform/bootstrap/settings/cega | 6 +
terraform/bootstrap/settings/instances/fin1 | 26 ++++
terraform/bootstrap/settings/instances/swe1 | 26 ++++
terraform/bootstrap/troubleshooting.md | 17 +++
terraform/hosts | 14 --
terraform/main.tf | 161 ++++++++++----------
terraform/network/main.tf | 24 ---
9 files changed, 274 insertions(+), 124 deletions(-)
create mode 100755 terraform/bootstrap/boot.sh
create mode 100644 terraform/bootstrap/settings/cega
create mode 100644 terraform/bootstrap/settings/instances/fin1
create mode 100644 terraform/bootstrap/settings/instances/swe1
create mode 100644 terraform/bootstrap/troubleshooting.md
delete mode 100644 terraform/hosts
delete mode 100644 terraform/network/main.tf
diff --git a/terraform/.gitignore b/terraform/.gitignore
index 0c74fa30..5ff54109 100644
--- a/terraform/.gitignore
+++ b/terraform/.gitignore
@@ -1,7 +1,7 @@
-ega.conf
main.auto.tfvars
-snic.cloud.rc
+main.tf
.terraform*
*.tfstate*
tests/
instances/workers/*.zip
+private
diff --git a/terraform/bootstrap/boot.sh b/terraform/bootstrap/boot.sh
new file mode 100755
index 00000000..233ff397
--- /dev/null
+++ b/terraform/bootstrap/boot.sh
@@ -0,0 +1,120 @@
+#!/usr/bin/env bash
+set -e
+
+HERE=$(dirname ${BASH_SOURCE[0]})
+PRIVATE=${HERE}/../private
+MAIN_TF=${HERE}/../main.tf
+LIB=${HERE}/lib
+SETTINGS=${HERE}/settings
+
+# Defaults
+VERBOSE=no
+FORCE=yes
+OPENSSL=openssl
+GPG=gpg
+GPG_CONF=gpgconf
+GPG_AGENT=gpg-agent
+
+function usage {
+ echo "Usage: $0 [options]"
+ echo -e "\nOptions are:"
+ echo -e "\t--openssl \tPath to the Openssl executable [Default: ${OPENSSL}]"
+ echo -e "\t--gpg \tPath to the GnuPG executable [Default: ${GPG}]"
+ echo -e "\t--gpgconf \tPath to the GnuPG conf executable [Default: ${GPG_CONF}]"
+ echo -e "\t--gpg-agent \tPath to the GnuPG agent executable [Default: ${GPG_AGENT}]"
+ echo ""
+ echo -e "\t--verbose, -v \tShow verbose output"
+ echo -e "\t--polite, -p \tDo not force the re-creation of the subfolders. Ask instead"
+ echo -e "\t--help, -h \tOutputs this message and exits"
+ echo -e "\t-- ... \tAny other options appearing after the -- will be ignored"
+ echo ""
+}
+
+# While there are arguments or '--' is reached
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --help|-h) usage; exit 0;;
+ --verbose|-v) VERBOSE=yes;;
+ --polite|-p) FORCE=no;;
+ --gpg) GPG=$2; shift;;
+ --gpgconf) GPG_CONF=$2; shift;;
+ --openssl) OPENSSL=$2; shift;;
+ --) shift; break;;
+ *) echo "$0: error - unrecognized option $1" 1>&2; usage; exit 1;; esac
+ shift
+done
+
+[[ $VERBOSE == 'no' ]] && echo -en "Bootstrapping "
+
+source ${LIB}/defs.sh
+
+INSTANCES=$(ls ${SETTINGS}/instances | xargs) # make it one line. ls -lx didn't work
+
+rm_politely ${PRIVATE}
+mkdir -p ${PRIVATE}/cega
+
+exec 2>${PRIVATE}/.err
+
+# Load the cega settings
+source ${SETTINGS}/cega
+
+cat > ${MAIN_TF} < ${PRIVATE}/hosts
+
+# And the CEGA files
+echo "LEGA_INSTANCES=${INSTANCES// /,}" > ${PRIVATE}/cega/env
+
+# Central EGA Users
+source ${LIB}/cega_users.sh
+
+# Generate the configuration for each instance
+for INSTANCE in ${INSTANCES}; do source ${LIB}/instance.sh; done
+
+# Central EGA Message Broker
+source ${LIB}/cega_mq.sh
+
+task_complete "Bootstrap complete"
diff --git a/terraform/bootstrap/settings/cega b/terraform/bootstrap/settings/cega
new file mode 100644
index 00000000..535363ed
--- /dev/null
+++ b/terraform/bootstrap/settings/cega
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+CEGA_PUBKEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcLiS1a/+ul3LOGsBvprYLk1a8XYx6isqkVXQ05PlPLOOs83Qv9aN+uh8YOaebPYK3qlXEH4Tbmk/WJTgJJVkhefNZK+Stk3Pkk6oUqwHfZ7+lDWCqP7/Cvm4+HvVsAO+HBhv/8AhKxk6AI7X0ongrWhJLLJDuraFEYmswKAJOWiuxyKM9EbmmAhocKEx9cUHxnj8Rr3EGJ9urCwQxAIclZUfB5SqHQaGv6ApmVs5S2x6F3RG6upx6eXop4h357psaH7HTi90u6aLEjNf3uYdoCyh8AphqZ6NDVamUCXciO+1jKV03gDBC7xuLCk4ZCF0uRMXoFTmmr77AL33LuysL fred@snic-cloud"
+
+CEGA_CIDR="192.168.100.0/24"
+CEGA_PRIVATE_IP="192.168.100.100"
diff --git a/terraform/bootstrap/settings/instances/fin1 b/terraform/bootstrap/settings/instances/fin1
new file mode 100644
index 00000000..19a38bcb
--- /dev/null
+++ b/terraform/bootstrap/settings/instances/fin1
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+LEGA_GREETINGS="Welcome to Local EGA Finland @ CSC"
+CEGA_MQ_PASSWORD=$(generate_password 16)
+CEGA_REST_PASSWORD=$(generate_password 16)
+
+SSL_SUBJ="/C=FI/ST=Finland/L=Helsinki/O=CSC/OU=SysDevs/CN=LocalEGA/emailAddress=ega@csc.fi"
+
+DB_USER=lega
+DB_PASSWORD=$(generate_password 16)
+DB_TRY=30
+
+GPG_NAME="EGA Finland"
+GPG_COMMENT="@CSC"
+GPG_EMAIL="ega@csc.fi"
+
+GPG_PASSPHRASE=$(generate_password 16)
+RSA_PASSPHRASE=$(generate_password 16)
+
+PUBKEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcLiS1a/+ul3LOGsBvprYLk1a8XYx6isqkVXQ05PlPLOOs83Qv9aN+uh8YOaebPYK3qlXEH4Tbmk/WJTgJJVkhefNZK+Stk3Pkk6oUqwHfZ7+lDWCqP7/Cvm4+HvVsAO+HBhv/8AhKxk6AI7X0ongrWhJLLJDuraFEYmswKAJOWiuxyKM9EbmmAhocKEx9cUHxnj8Rr3EGJ9urCwQxAIclZUfB5SqHQaGv6ApmVs5S2x6F3RG6upx6eXop4h357psaH7HTi90u6aLEjNf3uYdoCyh8AphqZ6NDVamUCXciO+1jKV03gDBC7xuLCk4ZCF0uRMXoFTmmr77AL33LuysL fred@snic-cloud"
+
+CIDR="192.168.40.0/24"
+WORKERS=2
+VAULT_SIZE=100
+INBOX_SIZE=200
+INBOX_PATH="/ega/inbox/"
diff --git a/terraform/bootstrap/settings/instances/swe1 b/terraform/bootstrap/settings/instances/swe1
new file mode 100644
index 00000000..55786467
--- /dev/null
+++ b/terraform/bootstrap/settings/instances/swe1
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+LEGA_GREETINGS="Welcome to Local EGA Sweden @ NBIS"
+CEGA_MQ_PASSWORD=$(generate_password 16)
+CEGA_REST_PASSWORD=$(generate_password 16)
+
+SSL_SUBJ="/C=SE/ST=Sweden/L=Uppsala/O=NBIS/OU=SysDevs/CN=LocalEGA/emailAddress=ega@nbis.se"
+
+DB_USER=lega
+DB_PASSWORD=$(generate_password 16)
+DB_TRY=30
+
+GPG_NAME="EGA Sweden"
+GPG_COMMENT="@NBIS"
+GPG_EMAIL="ega@nbis.se"
+
+GPG_PASSPHRASE=$(generate_password 16)
+RSA_PASSPHRASE=$(generate_password 16)
+
+PUBKEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcLiS1a/+ul3LOGsBvprYLk1a8XYx6isqkVXQ05PlPLOOs83Qv9aN+uh8YOaebPYK3qlXEH4Tbmk/WJTgJJVkhefNZK+Stk3Pkk6oUqwHfZ7+lDWCqP7/Cvm4+HvVsAO+HBhv/8AhKxk6AI7X0ongrWhJLLJDuraFEYmswKAJOWiuxyKM9EbmmAhocKEx9cUHxnj8Rr3EGJ9urCwQxAIclZUfB5SqHQaGv6ApmVs5S2x6F3RG6upx6eXop4h357psaH7HTi90u6aLEjNf3uYdoCyh8AphqZ6NDVamUCXciO+1jKV03gDBC7xuLCk4ZCF0uRMXoFTmmr77AL33LuysL fred@snic-cloud"
+
+CIDR="192.168.10.0/24"
+WORKERS=4
+VAULT_SIZE=150
+INBOX_SIZE=300
+INBOX_PATH="/ega/inbox/"
diff --git a/terraform/bootstrap/troubleshooting.md b/terraform/bootstrap/troubleshooting.md
new file mode 100644
index 00000000..d02ae63d
--- /dev/null
+++ b/terraform/bootstrap/troubleshooting.md
@@ -0,0 +1,17 @@
+# Troubleshooting
+
+* Use `-h` to see the possible options of each script, and `-v` for
+ verbose output.
+
+* If bootstrapping take more than a few seconds to run, it is usually
+ because your computer does not have enough entropy. You can use the
+ program `rng-tools` to solve this problem. E.g. on Debian/Ubuntu
+ system, install the software by
+
+ sudo apt-get install rng-tools
+
+ and then run
+
+ sudo rngd -r /dev/urandom
+
+
diff --git a/terraform/hosts b/terraform/hosts
deleted file mode 100644
index 0c90c502..00000000
--- a/terraform/hosts
+++ /dev/null
@@ -1,14 +0,0 @@
-127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
-::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
-
-192.168.10.10 ega-db
-192.168.10.11 ega-mq
-192.168.10.12 ega-keys
-
-192.168.10.13 ega-connectors
-192.168.10.14 ega-inbox
-192.168.10.15 ega-frontend
-192.168.10.16 ega-monitors
-192.168.10.17 ega-vault
-
-# Ignoring the workers
diff --git a/terraform/main.tf b/terraform/main.tf
index 5cd3948a..b20fa84f 100644
--- a/terraform/main.tf
+++ b/terraform/main.tf
@@ -4,15 +4,13 @@
variable os_username {}
variable os_password {}
-variable db_password {}
-variable pubkey {}
-
-variable rsa_home {}
-variable gpg_home {}
-variable gpg_certs {}
-variable gpg_passphrase {}
-variable lega_conf {}
-variable cidr { default = "192.168.10.0/24" }
+variable tenant_id {}
+variable tenant_name {}
+variable auth_url {}
+variable region {}
+variable domain_name {}
+variable router_id {}
+variable dns_servers { type = list }
terraform {
backend "local" {
@@ -24,85 +22,80 @@ terraform {
provider "openstack" {
user_name = "${var.os_username}"
password = "${var.os_password}"
- tenant_id = "e62c28337a094ea99571adfb0b97939f"
- tenant_name = "SNIC 2017/13-34"
- auth_url = "https://hpc2n.cloud.snic.se:5000/v3"
- region = "HPC2N"
- domain_name = "snic"
+ tenant_id = "${var.tenant_id}"
+ tenant_name = "${var.tenant_name}"
+ auth_url = "${var.auth_url}"
+ region = "${var.region}"
+ domain_name = "${var.domain_name}"
}
-# ========= Network =========
-module "network" {
- source = "./network"
- cidr = "${var.cidr}"
+module "cega" {
+ source = "./cega"
+ private_ip = "192.168.100.100"
+ cega_data = "bootstrap/../private/cega"
+ pubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcLiS1a/+ul3LOGsBvprYLk1a8XYx6isqkVXQ05PlPLOOs83Qv9aN+uh8YOaebPYK3qlXEH4Tbmk/WJTgJJVkhefNZK+Stk3Pkk6oUqwHfZ7+lDWCqP7/Cvm4+HvVsAO+HBhv/8AhKxk6AI7X0ongrWhJLLJDuraFEYmswKAJOWiuxyKM9EbmmAhocKEx9cUHxnj8Rr3EGJ9urCwQxAIclZUfB5SqHQaGv6ApmVs5S2x6F3RG6upx6eXop4h357psaH7HTi90u6aLEjNf3uYdoCyh8AphqZ6NDVamUCXciO+1jKV03gDBC7xuLCk4ZCF0uRMXoFTmmr77AL33LuysL fred@snic-cloud"
+ cidr = "192.168.100.0/24"
+ dns_servers = ${var.dns_servers}
+ router_id = "${var.router_id}"
}
-# ========= Key Pair =========
-resource "openstack_compute_keypair_v2" "ega_key" {
- name = "ega_key"
- public_key = "${var.pubkey}"
-}
+module "instance_fin1" {
+ source = "./instance"
+ instance = "fin1"
+ instance_data = "bootstrap/../private/fin1"
+ pubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcLiS1a/+ul3LOGsBvprYLk1a8XYx6isqkVXQ05PlPLOOs83Qv9aN+uh8YOaebPYK3qlXEH4Tbmk/WJTgJJVkhefNZK+Stk3Pkk6oUqwHfZ7+lDWCqP7/Cvm4+HvVsAO+HBhv/8AhKxk6AI7X0ongrWhJLLJDuraFEYmswKAJOWiuxyKM9EbmmAhocKEx9cUHxnj8Rr3EGJ9urCwQxAIclZUfB5SqHQaGv6ApmVs5S2x6F3RG6upx6eXop4h357psaH7HTi90u6aLEjNf3uYdoCyh8AphqZ6NDVamUCXciO+1jKV03gDBC7xuLCk4ZCF0uRMXoFTmmr77AL33LuysL fred@snic-cloud"
+ cidr = "192.168.40.0/24"
+ dns_servers = ${var.dns_servers}
+ router_id = "${var.router_id}"
-# ========= Instances as Modules =========
-module "db" {
- source = "./instances/db"
- db_password = "${var.db_password}"
- private_ip = "192.168.10.10"
- cidr = "${var.cidr}"
- ega_key = "${openstack_compute_keypair_v2.ega_key.name}"
- ega_net = "${module.network.net_id}"
-}
-module "mq" {
- source = "./instances/mq"
- private_ip = "192.168.10.11"
- cidr = "${var.cidr}"
- ega_key = "${openstack_compute_keypair_v2.ega_key.name}"
- ega_net = "${module.network.net_id}"
-}
-module "inbox" {
- source = "./instances/inbox"
- volume_size = 600
- db_password = "${var.db_password}"
- private_ip = "192.168.10.14"
- ega_key = "${openstack_compute_keypair_v2.ega_key.name}"
- ega_net = "${module.network.net_id}"
- lega_conf = "${base64encode("${file("${var.lega_conf}")}")}"
- cidr = "${var.cidr}"
-}
-module "frontend" {
- source = "./instances/frontend"
- private_ip = "192.168.10.15"
- ega_key = "${openstack_compute_keypair_v2.ega_key.name}"
- ega_net = "${module.network.net_id}"
- lega_conf = "${base64encode("${file("${var.lega_conf}")}")}"
-}
-module "monitors" {
- source = "./instances/monitors"
- private_ip = "192.168.10.16"
- cidr = "${var.cidr}"
- ega_key = "${openstack_compute_keypair_v2.ega_key.name}"
- ega_net = "${module.network.net_id}"
- lega_conf = "${base64encode("${file("${var.lega_conf}")}")}"
-}
-module "vault" {
- source = "./instances/vault"
- volume_size = 300
- private_ip = "192.168.10.17"
- ega_key = "${openstack_compute_keypair_v2.ega_key.name}"
- ega_net = "${module.network.net_id}"
- lega_conf = "${base64encode("${file("${var.lega_conf}")}")}"
+ db_user = "lega"
+ db_password = "V1INWEo7c5B5vHYX"
+ db_name = "lega"
+
+ ip_db = "192.168.40.10"
+ ip_mq = "192.168.40.11"
+ ip_inbox = "192.168.40.12"
+ ip_frontend = "192.168.40.13"
+ ip_monitors = "192.168.40.15"
+ ip_vault = "192.168.40.14"
+ ip_keys = "192.168.40.16"
+ ip_workers = ["192.168.40.101","192.168.40.102"]
+
+ greetings = "Welcome to Local EGA Finland @ CSC"
+
+ inbox_size = "200"
+ inbox_path = "/ega/inbox/"
+ vault_size = "100"
+
+ gpg_passphrase = "VltxALNWkbXFoygG"
}
-module "workers" {
- source = "./instances/workers"
- count = 4
- private_ip_keys = "192.168.10.12"
- private_ips = ["192.168.10.100","192.168.10.101","192.168.10.102","192.168.10.103"]
- cidr = "${var.cidr}"
- ega_key = "${openstack_compute_keypair_v2.ega_key.name}"
- ega_net = "${module.network.net_id}"
- lega_conf = "${base64encode("${file("${var.lega_conf}")}")}"
- rsa_home = "${var.rsa_home}"
- gpg_home = "${var.gpg_home}"
- gpg_passphrase = "${var.gpg_passphrase}"
- gpg_certs = "${var.gpg_certs}"
+module "instance_swe1" {
+ source = "./instance"
+ instance = "swe1"
+ instance_data = "bootstrap/../private/swe1"
+ pubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCcLiS1a/+ul3LOGsBvprYLk1a8XYx6isqkVXQ05PlPLOOs83Qv9aN+uh8YOaebPYK3qlXEH4Tbmk/WJTgJJVkhefNZK+Stk3Pkk6oUqwHfZ7+lDWCqP7/Cvm4+HvVsAO+HBhv/8AhKxk6AI7X0ongrWhJLLJDuraFEYmswKAJOWiuxyKM9EbmmAhocKEx9cUHxnj8Rr3EGJ9urCwQxAIclZUfB5SqHQaGv6ApmVs5S2x6F3RG6upx6eXop4h357psaH7HTi90u6aLEjNf3uYdoCyh8AphqZ6NDVamUCXciO+1jKV03gDBC7xuLCk4ZCF0uRMXoFTmmr77AL33LuysL fred@snic-cloud"
+ cidr = "192.168.10.0/24"
+ dns_servers = ${var.dns_servers}
+ router_id = "${var.router_id}"
+
+ db_user = "lega"
+ db_password = "HtXfJKUoilFJWnip"
+ db_name = "lega"
+
+ ip_db = "192.168.10.10"
+ ip_mq = "192.168.10.11"
+ ip_inbox = "192.168.10.12"
+ ip_frontend = "192.168.10.13"
+ ip_monitors = "192.168.10.15"
+ ip_vault = "192.168.10.14"
+ ip_keys = "192.168.10.16"
+ ip_workers = ["192.168.10.101","192.168.10.102","192.168.10.103","192.168.10.104"]
+
+ greetings = "Welcome to Local EGA Sweden @ NBIS"
+
+ inbox_size = "300"
+ inbox_path = "/ega/inbox/"
+ vault_size = "150"
+
+ gpg_passphrase = "xRZWFQTZLTRhkzeL"
}
diff --git a/terraform/network/main.tf b/terraform/network/main.tf
deleted file mode 100644
index 60c001d6..00000000
--- a/terraform/network/main.tf
+++ /dev/null
@@ -1,24 +0,0 @@
-variable cidr {}
-
-resource "openstack_networking_network_v2" "ega_net" {
- name = "ega_net"
- admin_state_up = "true"
-}
-
-resource "openstack_networking_subnet_v2" "ega_subnet" {
- network_id = "${openstack_networking_network_v2.ega_net.id}"
- name = "ega_subnet"
- cidr = "${var.cidr}"
- enable_dhcp = true
- ip_version = 4
- dns_nameservers = ["130.239.1.90","8.8.8.8"]
-}
-
-resource "openstack_networking_router_interface_v2" "ega_router_interface" {
- router_id = "1f852a3d-f7ea-45ae-9cba-3160c2029ba1"
- subnet_id = "${openstack_networking_subnet_v2.ega_subnet.id}"
-}
-
-output "net_id" {
- value = "${openstack_networking_network_v2.ega_net.id}"
-}
From 10abdc3022df188af6d53b0d54a1a30c36530c38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Haziza?=
Date: Tue, 14 Nov 2017 23:57:41 +0100
Subject: [PATCH 129/528] Reshaping
---
.gitignore | 131 -----------
src/.gitignore | 130 +++++++++++
terraform/.gitignore | 1 +
terraform/bootstrap/cega_mq.sh | 92 ++++++++
terraform/bootstrap/cega_users.sh | 70 ++++++
terraform/bootstrap/defs.sh | 60 +++++
terraform/bootstrap/instance.sh | 221 ++++++++++++++++++
terraform/bootstrap/{boot.sh => run.sh} | 70 +++---
.../{instances/fin1 => fin1.instance} | 14 +-
.../{instances/swe1 => swe1.instance} | 14 +-
terraform/instances/db/main.tf | 16 +-
terraform/main.tf | 101 --------
12 files changed, 647 insertions(+), 273 deletions(-)
create mode 100644 src/.gitignore
create mode 100644 terraform/bootstrap/cega_mq.sh
create mode 100644 terraform/bootstrap/cega_users.sh
create mode 100644 terraform/bootstrap/defs.sh
create mode 100644 terraform/bootstrap/instance.sh
rename terraform/bootstrap/{boot.sh => run.sh} (64%)
rename terraform/bootstrap/settings/{instances/fin1 => fin1.instance} (71%)
rename terraform/bootstrap/settings/{instances/swe1 => swe1.instance} (71%)
delete mode 100644 terraform/main.tf
diff --git a/.gitignore b/.gitignore
index 435ae831..00e2092f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,134 +6,3 @@ private/
loggers/
!src/lega/conf/loggers
storage
-
-# =====================================
-# Byte-compiled / optimized / DLL files
-# =====================================
-__pycache__/
-*.py[cod]
-*$py.class
-
-# =====================================
-# C extensions
-# =====================================
-*.so
-*.so.*
-*.o
-*.la
-
-# =====================================
-# Distribution / packaging
-# =====================================
-.Python
-env/
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-*.egg-info/
-.installed.cfg
-*.egg
-
-# =====================================
-# PyInstaller
-# =====================================
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# =====================================
-# Installer logs
-# =====================================
-pip-log.txt
-pip-delete-this-directory.txt
-
-# =====================================
-# Unit test / coverage reports
-# =====================================
-htmlcov/
-.tox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*,cover
-.hypothesis/
-
-# =====================================
-# Translations
-# =====================================
-*.mo
-*.pot
-
-# =====================================
-# Django stuff:
-# =====================================
-*.log
-local_settings.py
-
-# =====================================
-# Flask stuff:
-# =====================================
-instance/
-.webassets-cache
-
-# =====================================
-# Scrapy stuff:
-# =====================================
-.scrapy
-
-# =====================================
-# Sphinx documentation
-# =====================================
-docs/_build/
-
-# =====================================
-# PyBuilder
-# =====================================
-target/
-
-# =====================================
-# IPython Notebook
-# =====================================
-.ipynb_checkpoints
-
-# =====================================
-# pyenv
-# =====================================
-.python-version
-
-# =====================================
-# celery beat schedule file
-# =====================================
-celerybeat-schedule
-
-# =====================================
-# dotenv
-# =====================================
-.env
-
-# =====================================
-# virtualenv
-# =====================================
-venv/
-ENV/
-
-# =====================================
-# Spyder project settings
-# =====================================
-.spyderproject
-
-# =====================================
-# Rope project settings
-# =====================================
-.ropeproject
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 00000000..cbacd478
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,130 @@
+# =====================================
+# Byte-compiled / optimized / DLL files
+# =====================================
+__pycache__/
+*.py[cod]
+*$py.class
+
+# =====================================
+# C extensions
+# =====================================
+*.so
+*.so.*
+*.o
+*.la
+
+# =====================================
+# Distribution / packaging
+# =====================================
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# =====================================
+# PyInstaller
+# =====================================
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# =====================================
+# Installer logs
+# =====================================
+pip-log.txt
+pip-delete-this-directory.txt
+
+# =====================================
+# Unit test / coverage reports
+# =====================================
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+.hypothesis/
+
+# =====================================
+# Translations
+# =====================================
+*.mo
+*.pot
+
+# =====================================
+# Django stuff:
+# =====================================
+*.log
+local_settings.py
+
+# =====================================
+# Flask stuff:
+# =====================================
+instance/
+.webassets-cache
+
+# =====================================
+# Scrapy stuff:
+# =====================================
+.scrapy
+
+# =====================================
+# Sphinx documentation
+# =====================================
+docs/_build/
+
+# =====================================
+# PyBuilder
+# =====================================
+target/
+
+# =====================================
+# IPython Notebook
+# =====================================
+.ipynb_checkpoints
+
+# =====================================
+# pyenv
+# =====================================
+.python-version
+
+# =====================================
+# celery beat schedule file
+# =====================================
+celerybeat-schedule
+
+# =====================================
+# dotenv
+# =====================================
+.env
+
+# =====================================
+# virtualenv
+# =====================================
+venv/
+ENV/
+
+# =====================================
+# Spyder project settings
+# =====================================
+.spyderproject
+
+# =====================================
+# Rope project settings
+# =====================================
+.ropeproject
diff --git a/terraform/.gitignore b/terraform/.gitignore
index 5ff54109..d7a7efc5 100644
--- a/terraform/.gitignore
+++ b/terraform/.gitignore
@@ -5,3 +5,4 @@ main.tf
tests/
instances/workers/*.zip
private
+*.rc
diff --git a/terraform/bootstrap/cega_mq.sh b/terraform/bootstrap/cega_mq.sh
new file mode 100644
index 00000000..aec9c6f6
--- /dev/null
+++ b/terraform/bootstrap/cega_mq.sh
@@ -0,0 +1,92 @@
+#!/usr/bin/env bash
+set -e
+
+echomsg "Generating passwords for the Message Broker"
+
+function rabbitmq_hash {
+ # 1) Generate a random 32 bit salt
+ # 2) Concatenate that with the UTF-8 representation of the password
+ # 3) Take the SHA-256 hash
+ # 4) Concatenate the salt again
+ # 5) Convert to base64 encoding
+ local SALT=${2:-$(${OPENSSL:-openssl} rand -hex 4)}
+ {
+ printf ${SALT} | xxd -p -r
+ ( printf ${SALT} | xxd -p -r; printf $1 ) | ${OPENSSL:-openssl} dgst -binary -sha256
+ } | base64
+}
+
+function output_password_hashes {
+ declare -a tmp=()
+ for INSTANCE in ${INSTANCES}
+ do
+ CEGA_MQ_PASSWORD=$(awk -F= '/CEGA_MQ_PASSWORD/{print $2}' ${PRIVATE}/${INSTANCE}/.trace)
+ CEGA_MQ_HASH=$(rabbitmq_hash $CEGA_MQ_PASSWORD)
+ tmp+=("{\"name\":\"cega_${INSTANCE}\",\"password_hash\":\"${CEGA_MQ_HASH}\",\"hashing_algorithm\":\"rabbit_password_hashing_sha256\",\"tags\":\"administrator\"}")
+ done
+ join_by ",\n" "${tmp[@]}"
+}
+
+function output_vhosts {
+ declare -a tmp=()
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"name\":\"${INSTANCE}\"}")
+ done
+ join_by "," "${tmp[@]}"
+}
+
+function output_permissions {
+ declare -a tmp=()
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"user\":\"cega_${INSTANCE}\", \"vhost\":\"${INSTANCE}\", \"configure\":\".*\", \"write\":\".*\", \"read\":\".*\"}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+function output_queues {
+ declare -a tmp=()
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"name\":\"${INSTANCE}.v1.commands.file\", \"vhost\":\"${INSTANCE}\", \"durable\":true, \"auto_delete\":false, \"arguments\":{}}")
+ tmp+=("{\"name\":\"${INSTANCE}.v1.commands.completed\", \"vhost\":\"${INSTANCE}\", \"durable\":true, \"auto_delete\":false, \"arguments\":{}}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+function output_exchanges {
+ declare -a tmp=()
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"name\":\"localega.v1\", \"vhost\":\"${INSTANCE}\", \"type\":\"topic\", \"durable\":true, \"auto_delete\":false, \"internal\":false, \"arguments\":{}}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+
+function output_bindings {
+ declare -a tmp=()
+ for INSTANCE in ${INSTANCES}
+ do
+ tmp+=("{\"source\":\"localega.v1\",\"vhost\":\"${INSTANCE}\",\"destination_type\":\"queue\",\"arguments\":{},\"destination\":\"${INSTANCE}.v1.commands.file\",\"routing_key\":\"${INSTANCE}.file\"}")
+ tmp+=("{\"source\":\"localega.v1\",\"vhost\":\"${INSTANCE}\",\"destination_type\":\"queue\",\"arguments\":{},\"destination\":\"${INSTANCE}.v1.commands.completed\",\"routing_key\":\"${INSTANCE}.completed\"}")
+ done
+ join_by $',\n' "${tmp[@]}"
+}
+
+mkdir -p ${PRIVATE}/cega
+{
+ echo '{"rabbit_version":"3.6.11",'
+ echo -n ' "users":['; output_password_hashes; echo '],'
+ echo -n ' "vhosts":['; output_vhosts; echo '],'
+ echo -n ' "permissions":['; output_permissions; echo '],'
+ echo ' "parameters":[],'
+ echo -n ' "global_parameters":[{"name":"cluster_name", "value":"rabbit@localhost"}],'
+ echo ' "policies":[],'
+ echo -n ' "queues":['; output_queues; echo '],'
+ echo -n ' "exchanges":['; output_exchanges; echo '],'
+ echo -n ' "bindings":['; output_bindings; echo ']'
+ echo '}'
+} > ${PRIVATE}/cega/defs.json
+
diff --git a/terraform/bootstrap/cega_users.sh b/terraform/bootstrap/cega_users.sh
new file mode 100644
index 00000000..4d596919
--- /dev/null
+++ b/terraform/bootstrap/cega_users.sh
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+set -e
+
+echomsg "Generating fake Central EGA users"
+
+[[ -x $(readlink ${OPENSSL}) ]] && echo "${OPENSSL} is not executable. Adjust the setting with --openssl" && exit 3
+
+mkdir -p ${PRIVATE}/cega/users
+
+EGA_USER_PASSWORD_JOHN=$(generate_password 16)
+EGA_USER_PASSWORD_JANE=$(generate_password 16)
+EGA_USER_PASSWORD_TAYLOR=$(generate_password 16)
+
+EGA_USER_PUBKEY_JOHN=${PRIVATE}/cega/users/john.pub
+EGA_USER_SECKEY_JOHN=${PRIVATE}/cega/users/john.sec
+
+EGA_USER_PUBKEY_JANE=${PRIVATE}/cega/users/jane.pub
+EGA_USER_SECKEY_JANE=${PRIVATE}/cega/users/jane.sec
+
+${OPENSSL} genrsa -out ${EGA_USER_SECKEY_JOHN} -passout pass:${EGA_USER_PASSWORD_JOHN} 2048
+${OPENSSL} rsa -in ${EGA_USER_SECKEY_JOHN} -passin pass:${EGA_USER_PASSWORD_JOHN} -pubout -out ${EGA_USER_PUBKEY_JOHN}
+chmod 400 ${EGA_USER_SECKEY_JOHN}
+
+${OPENSSL} genrsa -out ${EGA_USER_SECKEY_JANE} -passout pass:${EGA_USER_PASSWORD_JANE} 2048
+${OPENSSL} rsa -in ${EGA_USER_SECKEY_JANE} -passin pass:${EGA_USER_PASSWORD_JANE} -pubout -out ${EGA_USER_PUBKEY_JANE}
+chmod 400 ${EGA_USER_SECKEY_JANE}
+
+cat > ${PRIVATE}/cega/users/john.yml < ${PRIVATE}/cega/users/jane.yml < ${PRIVATE}/cega/users/taylor.yml <> ${PRIVATE}/cega/.trace < $1 \xF0\x9F\x91\x8D"
+ else
+ echo -e " \xF0\x9F\x91\x8D"
+ fi
+}
+
+
+function backup {
+ local target=$1
+ if [[ -e $target ]] && [[ $FORCE != 'yes' ]]; then
+ echomsg "Backing up $target"
+ mv -f $target $target.$(date +"%Y-%m-%d_%H:%M:%S")
+ fi
+}
+
+function rm_politely {
+ local FOLDER=$1
+
+ if [[ -d $FOLDER ]]; then
+ if [[ $FORCE == 'yes' ]]; then
+ rm -rf $FOLDER
+ else
+ # Asking
+ echo "[Warning] The folder \"$FOLDER\" already exists. "
+ while : ; do # while = In a subshell
+ echo -n "[Warning] "
+ echo -n -e "Proceed to re-create it? [y/N] "
+ read -t 10 yn
+ case $yn in
+ y) rm -rf $FOLDER; break;;
+ N) echo "Ok. Choose another private directory. Exiting"; exit 1;;
+ *) echo "Eh?";;
+ esac
+ done
+ fi
+ fi
+}
+
+function generate_password {
+ local size=${1:-16} # defaults to 16 characters
+ p=$(python3.6 -c "import secrets,string;print(''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(${size})))")
+ echo $p
+}
+
+
+function join_by { local IFS="$1"; shift; echo -n "$*"; }
diff --git a/terraform/bootstrap/instance.sh b/terraform/bootstrap/instance.sh
new file mode 100644
index 00000000..2db4cdc9
--- /dev/null
+++ b/terraform/bootstrap/instance.sh
@@ -0,0 +1,221 @@
+#!/usr/bin/env bash
+
+echomsg "Generating private data for ${INSTANCE} [Default in ${SETTINGS}/${INSTANCE}]"
+
+########################################################
+# Loading the instance's settings
+
+if [[ -f ${SETTINGS}/${INSTANCE}.instance ]]; then
+ source ${SETTINGS}/${INSTANCE}.instance
+else
+ echo "No settings found for ${INSTANCE}"
+ exit 1
+fi
+
+[[ -x $(readlink ${GPG}) ]] && echo "${GPG} is not executable. Adjust the setting with --gpg" && exit 2
+[[ -x $(readlink ${OPENSSL}) ]] && echo "${OPENSSL} is not executable. Adjust the setting with --openssl" && exit 3
+
+if [ -z "${DB_USER}" -o "${DB_USER}" == "postgres" ]; then
+ echo "Choose a database user (but not 'postgres')"
+ exit 4
+fi
+
+#########################################################################
+# And....cue music
+#########################################################################
+
+mkdir -p ${PRIVATE}/${INSTANCE}/{gpg,rsa,certs}
+chmod 700 ${PRIVATE}/${INSTANCE}/{gpg,rsa,certs}
+
+echomsg "\t* the GnuPG key"
+
+cat > ${PRIVATE}/${INSTANCE}/gen_key < ${PRIVATE}/${INSTANCE}/keys.conf < ${PRIVATE}/${INSTANCE}/ega.conf <> ${PRIVATE}/cega/env < ${PRIVATE}/${INSTANCE}/auth.conf < 1 ]] && echo -n ','
+ echo -n "\"${PRIVATE_IPS[worker_${i}]}\""
+ done
+}
+
+cat >> main.tf <> ${PRIVATE}/hosts; done
+
+cat >> ${PRIVATE}/${INSTANCE}/.trace <