diff --git a/.github/workflows/cd-pipeline.yml b/.github/workflows/cd-pipeline.yml
index 8f58c936c5..87ce72e954 100644
--- a/.github/workflows/cd-pipeline.yml
+++ b/.github/workflows/cd-pipeline.yml
@@ -14,6 +14,7 @@ on: # rebuild any PRs and main branch changes
- 'bitnami/discourse/**'
- 'bitnami/dokuwiki/**'
- 'bitnami/drupal/**'
+ - 'bitnami/ejbca/**'
- 'bitnami/elasticsearch/**'
- 'bitnami/etcd/**'
- 'bitnami/external-dns/**'
diff --git a/.vib/ejbca/cypress/cypress.json b/.vib/ejbca/cypress/cypress.json
new file mode 100644
index 0000000000..093e969ee0
--- /dev/null
+++ b/.vib/ejbca/cypress/cypress.json
@@ -0,0 +1,8 @@
+{
+ "baseUrl": "http://localhost",
+ "env": {
+ "username": "bitnamiTest",
+ "password": "ComplicatedPassword123!4",
+ "baseDN": "UID=c-1CCXmPAsNWmZuDtQQ8FHl7tcVdjCiNTH,O=ExampleCA,C=SE"
+ }
+}
\ No newline at end of file
diff --git a/.vib/ejbca/cypress/cypress/fixtures/certs.json b/.vib/ejbca/cypress/cypress/fixtures/certs.json
new file mode 100644
index 0000000000..de4df283e8
--- /dev/null
+++ b/.vib/ejbca/cypress/cypress/fixtures/certs.json
@@ -0,0 +1,6 @@
+{
+ "newAdminCert": {
+ "cipherSpec": "RSA_2048",
+ "profile": "ENDUSER"
+ }
+}
diff --git a/.vib/ejbca/cypress/cypress/integration/ejbca_spec.js b/.vib/ejbca/cypress/cypress/integration/ejbca_spec.js
new file mode 100644
index 0000000000..781584a452
--- /dev/null
+++ b/.vib/ejbca/cypress/cypress/integration/ejbca_spec.js
@@ -0,0 +1,40 @@
+///
+
+it('allows to enrol and verify certificate', () => {
+ const certFile = `cypress/downloads/${Cypress.env('username')}.p12`;
+ cy.task('fileExists', certFile).then((exists) => {
+ // A user can only enrol once
+ if (!exists) {
+ cy.visit('/ejbca/enrol/keystore.jsp');
+ cy.get('#textfieldusername').type(Cypress.env('username'));
+ cy.get('#textfieldpassword').type(Cypress.env('password'));
+ cy.get('#buttonsubmitusername').click();
+ cy.fixture('certs').then((certs) => {
+ cy.get('#tokenKeySpec').select(certs.newAdminCert.cipherSpec);
+ cy.get('#certprofile').select(certs.newAdminCert.profile);
+ });
+ // Clicking on the button will download the certificate, but Cypress
+ // expects the page to be reloaded and fails with a timeout. We manually
+ // force the reload to avoid it and then verify that the file was indeed
+ // downloaded.
+ cy.window()
+ .document()
+ .then(function (doc) {
+ doc.addEventListener('click', () => {
+ setTimeout(function () {
+ doc.location.reload();
+ }, 2000);
+ });
+
+ cy.contains('input', 'Enroll').click();
+ });
+ }
+ cy.readFile(certFile).should('exist');
+ });
+
+ cy.visit('/ejbca/retrieve/list_certs.jsp');
+ cy.get('#subject').type(`${Cypress.env('baseDN')},CN=SuperAdmin`);
+ cy.get('#ok').click();
+ cy.contains('Check if certificate is revoked').click();
+ cy.contains('has NOT been revoked');
+});
diff --git a/.vib/ejbca/cypress/cypress/plugins/index.js b/.vib/ejbca/cypress/cypress/plugins/index.js
new file mode 100644
index 0000000000..273aa37869
--- /dev/null
+++ b/.vib/ejbca/cypress/cypress/plugins/index.js
@@ -0,0 +1,27 @@
+///
+// ***********************************************************
+// This example plugins/index.js can be used to load plugins
+//
+// You can change the location of this file or turn off loading
+// the plugins file with the 'pluginsFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/plugins-guide
+// ***********************************************************
+
+// This function is called when a project is opened or re-opened (e.g. due to
+// the project's config changing)
+
+/**
+ * @type {Cypress.PluginConfig}
+ */
+// eslint-disable-next-line no-unused-vars
+const fs = require('fs');
+
+module.exports = (on, config) => {
+ on('task', {
+ fileExists(filename) {
+ return fs.existsSync(filename);
+ },
+ });
+};
diff --git a/.vib/ejbca/cypress/cypress/support/commands.js b/.vib/ejbca/cypress/cypress/support/commands.js
new file mode 100644
index 0000000000..db6590fd8c
--- /dev/null
+++ b/.vib/ejbca/cypress/cypress/support/commands.js
@@ -0,0 +1,13 @@
+const COMMAND_DELAY = 2000;
+
+for (const command of ['click']) {
+ Cypress.Commands.overwrite(command, (originalFn, ...args) => {
+ const origVal = originalFn(...args);
+
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve(origVal);
+ }, COMMAND_DELAY);
+ });
+ });
+}
\ No newline at end of file
diff --git a/.vib/ejbca/cypress/cypress/support/index.js b/.vib/ejbca/cypress/cypress/support/index.js
new file mode 100644
index 0000000000..37a498fb5b
--- /dev/null
+++ b/.vib/ejbca/cypress/cypress/support/index.js
@@ -0,0 +1,20 @@
+// ***********************************************************
+// This example support/index.js is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import './commands';
+
+// Alternatively you can use CommonJS syntax:
+// require('./commands')
diff --git a/.vib/ejbca/goss/goss.yaml b/.vib/ejbca/goss/goss.yaml
new file mode 100644
index 0000000000..ef53f8bf48
--- /dev/null
+++ b/.vib/ejbca/goss/goss.yaml
@@ -0,0 +1,38 @@
+http:
+ https://ejbca:{{ .Vars.service.ports.https }}:
+ status: 200
+ allow-insecure: true
+file:
+ /bitnami/ejbca:
+ exists: true
+ filetype: directory
+ mode: "0775"
+ owner: root
+ /opt/bitnami/wildfly/standalone/configuration/standalone.xml:
+ exists: true
+ filetype: file
+ mode: "0644"
+ contains:
+ - /http.*{{ .Vars.containerPorts.http }}/
+ - /https.*{{ .Vars.containerPorts.https }}/
+ - /connection-url.*{{ .Vars.mariadb.auth.database }}/
+ - /user-name.*{{ .Vars.mariadb.auth.username }}/
+ - /password.*{{ .Vars.mariadb.auth.password }}/
+command:
+ {{- $baseDN := .Vars.ejbcaCA.baseDN }}
+ {{- $caName := .Vars.ejbcaCA.name }}
+ {{- $user := printf "user_%s" (randAlpha 5) }}
+ {{- $pass := printf "%s" (randAlpha 5) }}
+ {{- $dn := printf "%s,CN=%s" $baseDN $user }}
+ # Identity type 1 corresponds to END-USER
+ {{- $identityType := "1" }}
+ add-identity-export-cert:
+ exec: ejbca.sh ra addendentity --username '{{ $user }}' --caname '{{ $caName}}' --dn '{{ $dn }}' --type {{ $identityType }} --token P12 --password '{{ $pass }}' && ejbca.sh ra setclearpwd '{{ $user }}' '{{ $pass }}' && ejbca.sh batch && ls ./p12/{{ $user }}.p12
+ exit-status: 0
+ timeout: 20000
+ check-user-info:
+ exec: id
+ exit-status: 0
+ stdout:
+ - uid={{ .Vars.containerSecurityContext.runAsUser }}
+ - /groups=.*{{ .Vars.podSecurityContext.fsGroup }}/
diff --git a/.vib/ejbca/goss/vars.yaml b/.vib/ejbca/goss/vars.yaml
new file mode 100644
index 0000000000..09a7d2767a
--- /dev/null
+++ b/.vib/ejbca/goss/vars.yaml
@@ -0,0 +1,18 @@
+ejbcaCA:
+ name: ManagementTestCA
+ baseDN: "UID=c-1CCXmPAsNWmZuDtQQ8FHl7tcVdjCiNTH,O=ExampleCA,C=SE"
+podSecurityContext:
+ fsGroup: 1002
+containerSecurityContext:
+ runAsUser: 1002
+containerPorts:
+ http: 8081
+ https: 8443
+service:
+ ports:
+ https: 8444
+mariadb:
+ auth:
+ database: bitnami_ejbca_test
+ username: bn_ejbca_test
+ password: bn_ejbca_pass_test
\ No newline at end of file
diff --git a/.vib/ejbca/vib-publish.json b/.vib/ejbca/vib-publish.json
index b79de6cdca..5bb4724ea3 100644
--- a/.vib/ejbca/vib-publish.json
+++ b/.vib/ejbca/vib-publish.json
@@ -22,11 +22,11 @@
"url": "{SHA_ARCHIVE}",
"path": "/bitnami/ejbca"
},
- "runtime_parameters": "ImVqYmNhQWRtaW5QYXNzd29yZCI6ICJCaXRuYW1pMTIzNCIKImVqYmNhQWRtaW5Vc2VybmFtZSI6ICJzdXBlcmFkbWluIgoic2VydmljZSI6CiAgInBvcnRzIjoKICAgICJodHRwIjogODAKICAidHlwZSI6ICJMb2FkQmFsYW5jZXIi",
+ "runtime_parameters": "ZWpiY2FBZG1pblVzZXJuYW1lOiBiaXRuYW1pVGVzdAplamJjYUFkbWluUGFzc3dvcmQ6ICJDb21wbGljYXRlZFBhc3N3b3JkMTIzITQiCmVqYmNhQ0E6CiAgbmFtZTogTWFuYWdlbWVudFRlc3RDQQogIGJhc2VETjogIlVJRD1jLTFDQ1htUEFzTldtWnVEdFFROEZIbDd0Y1ZkakNpTlRILE89RXhhbXBsZUNBLEM9U0UiCnBvZFNlY3VyaXR5Q29udGV4dDoKICBlbmFibGVkOiB0cnVlCiAgZnNHcm91cDogMTAwMgpjb250YWluZXJTZWN1cml0eUNvbnRleHQ6CiAgZW5hYmxlZDogdHJ1ZQogIHJ1bkFzVXNlcjogMTAwMgpjb250YWluZXJQb3J0czoKICBodHRwOiA4MDgxCiAgaHR0cHM6IDg0NDMKc2VydmljZToKICB0eXBlOiBMb2FkQmFsYW5jZXIKICBwb3J0czoKICAgIGh0dHA6IDgwCiAgICBodHRwczogODQ0NAogIGFkdmVydGlzZWRIdHRwc1BvcnQ6IDg0NDQKbWFyaWFkYjoKICBlbmFibGVkOiB0cnVlCiAgYXV0aDoKICAgIGRhdGFiYXNlOiBiaXRuYW1pX2VqYmNhX3Rlc3QKICAgIHVzZXJuYW1lOiBibl9lamJjYV90ZXN0CiAgICBwYXNzd29yZDogYm5fZWpiY2FfcGFzc190ZXN0",
"target_platform": {
"target_platform_id": "{VIB_ENV_TARGET_PLATFORM}",
"size": {
- "name": "S4"
+ "name": "M4"
}
}
},
@@ -37,6 +37,28 @@
"endpoint": "lb-ejbca-http",
"app_protocol": "HTTP"
}
+ },
+ {
+ "action_id": "goss",
+ "params": {
+ "resources": {
+ "path": "/.vib/ejbca/goss"
+ },
+ "remote": {
+ "workload": "deploy-ejbca"
+ },
+ "vars_file": "vars.yaml"
+ }
+ },
+ {
+ "action_id": "cypress",
+ "params": {
+ "resources": {
+ "path": "/.vib/ejbca/cypress"
+ },
+ "endpoint": "lb-ejbca-http",
+ "app_protocol": "HTTP"
+ }
}
]
},
diff --git a/.vib/ejbca/vib-verify.json b/.vib/ejbca/vib-verify.json
index aa8b947d78..d2aa8cff89 100644
--- a/.vib/ejbca/vib-verify.json
+++ b/.vib/ejbca/vib-verify.json
@@ -22,11 +22,11 @@
"url": "{SHA_ARCHIVE}",
"path": "/bitnami/ejbca"
},
- "runtime_parameters": "ImVqYmNhQWRtaW5QYXNzd29yZCI6ICJCaXRuYW1pMTIzNCIKImVqYmNhQWRtaW5Vc2VybmFtZSI6ICJzdXBlcmFkbWluIgoic2VydmljZSI6CiAgInBvcnRzIjoKICAgICJodHRwIjogODAKICAidHlwZSI6ICJMb2FkQmFsYW5jZXIi",
+ "runtime_parameters": "ZWpiY2FBZG1pblVzZXJuYW1lOiBiaXRuYW1pVGVzdAplamJjYUFkbWluUGFzc3dvcmQ6ICJDb21wbGljYXRlZFBhc3N3b3JkMTIzITQiCmVqYmNhQ0E6CiAgbmFtZTogTWFuYWdlbWVudFRlc3RDQQogIGJhc2VETjogIlVJRD1jLTFDQ1htUEFzTldtWnVEdFFROEZIbDd0Y1ZkakNpTlRILE89RXhhbXBsZUNBLEM9U0UiCnBvZFNlY3VyaXR5Q29udGV4dDoKICBlbmFibGVkOiB0cnVlCiAgZnNHcm91cDogMTAwMgpjb250YWluZXJTZWN1cml0eUNvbnRleHQ6CiAgZW5hYmxlZDogdHJ1ZQogIHJ1bkFzVXNlcjogMTAwMgpjb250YWluZXJQb3J0czoKICBodHRwOiA4MDgxCiAgaHR0cHM6IDg0NDMKc2VydmljZToKICB0eXBlOiBMb2FkQmFsYW5jZXIKICBwb3J0czoKICAgIGh0dHA6IDgwCiAgICBodHRwczogODQ0NAogIGFkdmVydGlzZWRIdHRwc1BvcnQ6IDg0NDQKbWFyaWFkYjoKICBlbmFibGVkOiB0cnVlCiAgYXV0aDoKICAgIGRhdGFiYXNlOiBiaXRuYW1pX2VqYmNhX3Rlc3QKICAgIHVzZXJuYW1lOiBibl9lamJjYV90ZXN0CiAgICBwYXNzd29yZDogYm5fZWpiY2FfcGFzc190ZXN0",
"target_platform": {
"target_platform_id": "{VIB_ENV_TARGET_PLATFORM}",
"size": {
- "name": "S4"
+ "name": "M4"
}
}
},
@@ -37,6 +37,28 @@
"endpoint": "lb-ejbca-http",
"app_protocol": "HTTP"
}
+ },
+ {
+ "action_id": "goss",
+ "params": {
+ "resources": {
+ "path": "/.vib/ejbca/goss"
+ },
+ "remote": {
+ "workload": "deploy-ejbca"
+ },
+ "vars_file": "vars.yaml"
+ }
+ },
+ {
+ "action_id": "cypress",
+ "params": {
+ "resources": {
+ "path": "/.vib/ejbca/cypress"
+ },
+ "endpoint": "lb-ejbca-http",
+ "app_protocol": "HTTP"
+ }
}
]
}