diff --git a/.github/workflows/cd-pipeline.yml b/.github/workflows/cd-pipeline.yml index e925733df0..a8ed80cadf 100644 --- a/.github/workflows/cd-pipeline.yml +++ b/.github/workflows/cd-pipeline.yml @@ -34,6 +34,7 @@ on: # rebuild any PRs and main branch changes - 'bitnami/kafka/**' - 'bitnami/keycloak/**' - 'bitnami/kibana/**' + - 'bitnami/kong/**' - 'bitnami/logstash/**' - 'bitnami/magento/**' - 'bitnami/mariadb-galera/**' diff --git a/.vib/kong/cypress/cypress.json b/.vib/kong/cypress/cypress.json new file mode 100644 index 0000000000..ac2d78f0b5 --- /dev/null +++ b/.vib/kong/cypress/cypress.json @@ -0,0 +1,10 @@ +{ + "baseUrl": "http://localhost", + "env": { + "apikey": "ComplicatedPassword123!4", + "ingressHost": "www.example.com", + "ingressPath": "/nginx", + "externalIp": "{{ TARGET_IP }}", + "adminHttpPort": "443" + } +} diff --git a/.vib/kong/cypress/cypress/fixtures/routes.json b/.vib/kong/cypress/cypress/fixtures/routes.json new file mode 100644 index 0000000000..dad3d621bb --- /dev/null +++ b/.vib/kong/cypress/cypress/fixtures/routes.json @@ -0,0 +1,5 @@ +{ + "newRoute": { + "path": "/chestnut" + } +} diff --git a/.vib/kong/cypress/cypress/fixtures/services.json b/.vib/kong/cypress/cypress/fixtures/services.json new file mode 100644 index 0000000000..fe4612ab36 --- /dev/null +++ b/.vib/kong/cypress/cypress/fixtures/services.json @@ -0,0 +1,7 @@ +{ + "newService": { + "name": "cypress-service", + "upstreamURL": "https://bitnami.com", + "upstreamContent": "Loved by Developers" + } +} diff --git a/.vib/kong/cypress/cypress/integration/kong_spec.js b/.vib/kong/cypress/cypress/integration/kong_spec.js new file mode 100644 index 0000000000..0252517315 --- /dev/null +++ b/.vib/kong/cypress/cypress/integration/kong_spec.js @@ -0,0 +1,73 @@ +/// + +import { random } from '../support/utils'; + +it('allows accessing a restricted service (CRD) when API key is presented', () => { + const ROUTE_PATH = Cypress.env('ingressPath'); + + cy.request({ + method: 'GET', + url: ROUTE_PATH, + headers: { Host: Cypress.env('ingressHost') }, + failOnStatusCode: false, + }).then((response) => { + // No API Key presented + expect(response.status).to.eq(401); + }); + + cy.request({ + method: 'GET', + url: ROUTE_PATH, + headers: { + apikey: Cypress.env('apikey'), + Host: Cypress.env('ingressHost'), + }, + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.body).to.contain('Welcome to nginx'); + }); +}); + +it('allows adding a new service and route through admin API', () => { + // As adminAPI is exposed in another port, we need to use the external IP to access it + const BASE_URL = `http://${Cypress.env('externalIp')}:${Cypress.env( + 'adminHttpPort' + )}`; + + cy.fixture('services').then((services) => { + cy.request({ + method: 'POST', + url: `${BASE_URL}/services`, + body: { + name: `${services.newService.name}-${random}`, + url: services.newService.upstreamURL, + }, + }).then((response) => { + expect(response.status).to.eq(201); + }); + + cy.fixture('routes').then((routes) => { + cy.request({ + method: 'POST', + url: `${BASE_URL}/services/${services.newService.name}-${random}/routes`, + body: { + paths: [ + `${routes.newRoute.path}${random}` + ], + }, + }).then((response) => { + expect(response.status).to.eq(201); + }); + + // Changes takes some seconds to apply + cy.wait(7000); + cy.request({ + method: 'GET', + url: `${routes.newRoute.path}${random}`, + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.body).to.contain(services.newService.upstreamContent); + }); + }); + }); +}); diff --git a/.vib/kong/cypress/cypress/support/utils.js b/.vib/kong/cypress/cypress/support/utils.js new file mode 100644 index 0000000000..f0217c9773 --- /dev/null +++ b/.vib/kong/cypress/cypress/support/utils.js @@ -0,0 +1,3 @@ +/// + +export let random = (Math.random() + 1).toString(36).substring(7); diff --git a/.vib/kong/goss/goss.yaml b/.vib/kong/goss/goss.yaml new file mode 100644 index 0000000000..0582e25c21 --- /dev/null +++ b/.vib/kong/goss/goss.yaml @@ -0,0 +1,33 @@ +http: + https://kong:{{ .Vars.service.ports.proxyHttps }}: + # The proxy does respond but the route is not registered + status: 404 + allow-insecure: true + https://kong:{{ .Vars.service.ports.adminHttps }}: + status: 200 + allow-insecure: true +file: + /opt/bitnami/kong/conf/kong.conf: + exists: true + filetype: file + mode: '0644' + owner: root + contains: + - /pg_user.*{{ .Vars.postgresql.auth.username }}/ + - /pg_database.*{{ .Vars.postgresql.auth.database }}/ + - /pg_password.*{{ .Vars.postgresql.auth.password }}/ + /opt/bitnami/kong/server/nginx-kong.conf: + exists: true + filetype: file + mode: '0644' + contains: + - /listen.*{{ .Vars.kong.containerPorts.proxyHttp }}/ + - /listen.*{{ .Vars.kong.containerPorts.adminHttp }}/ + - /listen.*{{ .Vars.kong.containerPorts.proxyHttps }}.*ssl/ + - /listen.*{{ .Vars.kong.containerPorts.adminHttps }}.*ssl/ +command: + check-user-info: + exec: id + exit-status: 0 + stdout: + - uid={{ .Vars.containerSecurityContext.runAsUser }} \ No newline at end of file diff --git a/.vib/kong/goss/vars.yaml b/.vib/kong/goss/vars.yaml new file mode 100644 index 0000000000..f964271c37 --- /dev/null +++ b/.vib/kong/goss/vars.yaml @@ -0,0 +1,17 @@ +containerSecurityContext: + runAsUser: 1002 +kong: + containerPorts: + proxyHttp: 8000 + proxyHttps: 8443 + adminHttp: 8001 + adminHttps: 8444 +service: + ports: + proxyHttps: 8443 + adminHttps: 8444 +postgresql: + auth: + username: kong + password: "" + database: kong \ No newline at end of file diff --git a/.vib/kong/vib-action.config b/.vib/kong/vib-action.config new file mode 100644 index 0000000000..98dc98a97e --- /dev/null +++ b/.vib/kong/vib-action.config @@ -0,0 +1 @@ +verification-mode=SERIAL \ No newline at end of file diff --git a/.vib/kong/vib-publish.json b/.vib/kong/vib-publish.json index 9cd48b4f53..0cf9013a10 100644 --- a/.vib/kong/vib-publish.json +++ b/.vib/kong/vib-publish.json @@ -22,7 +22,7 @@ "url": "{SHA_ARCHIVE}", "path": "/bitnami/kong" }, - "runtime_parameters": "InBvZEFmZmluaXR5UHJlc2V0IjogImhhcmQiCiJwb2RBbnRpQWZmaW5pdHlQcmVzZXQiOiAiIgoicG9zdGdyZXNxbCI6CiAgInBvc3RncmVzcWxQYXNzd29yZCI6ICI3ZE14TGZjcXhOIgoicmVwbGljYUNvdW50IjogMQoic2VydmljZSI6CiAgInByb3h5SHR0cFBvcnQiOiA4MAogICJ0eXBlIjogIkxvYWRCYWxhbmNlciI=", + "runtime_parameters": "cmVwbGljYUNvdW50OiAxCmRhdGFiYXNlOiBwb3N0Z3Jlc3FsCmNvbnRhaW5lclNlY3VyaXR5Q29udGV4dDoKICBlbmFibGVkOiB0cnVlCiAgcnVuQXNVc2VyOiAxMDAyCmtvbmc6CiAgY29udGFpbmVyUG9ydHM6IAogICAgcHJveHlIdHRwOiA4MDAwCiAgICBwcm94eUh0dHBzOiA4NDQzCiAgICBhZG1pbkh0dHA6IDgwMDEKICAgIGFkbWluSHR0cHM6IDg0NDQKc2VydmljZToKICB0eXBlOiBMb2FkQmFsYW5jZXIKICBleHBvc2VBZG1pbjogdHJ1ZQogIGRpc2FibGVIdHRwUG9ydDogZmFsc2UKICBwb3J0czoKICAgIHByb3h5SHR0cDogODAKICAgIHByb3h5SHR0cHM6IDg0NDMKICAgIGFkbWluSHR0cDogNDQzCiAgICBhZG1pbkh0dHBzOiA4NDQ0CmluZ3Jlc3NDb250cm9sbGVyOgogIGVuYWJsZWQ6IHRydWUKICBpbmdyZXNzQ2xhc3M6IGtvbmcKcG9zdGdyZXNxbDoKICBlbmFibGVkOiB0cnVlCiAgYXV0aDoKICAgIHVzZXJuYW1lOiBrb25nCiAgICBwYXNzd29yZDogIiIKICAgIGRhdGFiYXNlOiBrb25nCmV4dHJhRGVwbG95OgotIGFwaVZlcnNpb246IGFwcHMvdjEKICBraW5kOiBEZXBsb3ltZW50CiAgbWV0YWRhdGE6CiAgICBuYW1lOiBuZ2lueC12aWItdGVzdHMKICBzcGVjOgogICAgcmVwbGljYXM6IDEKICAgIHNlbGVjdG9yOgogICAgICBtYXRjaExhYmVsczoKICAgICAgICBhcHA6IG5naW54CiAgICB0ZW1wbGF0ZToKICAgICAgbWV0YWRhdGE6CiAgICAgICAgbGFiZWxzOgogICAgICAgICAgYXBwOiBuZ2lueAogICAgICBzcGVjOgogICAgICAgIGNvbnRhaW5lcnM6CiAgICAgICAgLSBuYW1lOiBuZ2lueAogICAgICAgICAgaW1hZ2U6IGJpdG5hbWkvbmdpbngKICAgICAgICAgIHBvcnRzOgogICAgICAgICAgLSBjb250YWluZXJQb3J0OiA4MDgwCi0gYXBpVmVyc2lvbjogdjEKICBraW5kOiBTZXJ2aWNlCiAgbWV0YWRhdGE6CiAgICBuYW1lOiBuZ2lueC12aWItdGVzdHMKICAgIGxhYmVsczoKICAgICAgYXBwOiBuZ2lueAogIHNwZWM6CiAgICBzZWxlY3RvcjoKICAgICAgYXBwOiBuZ2lueAogICAgcG9ydHM6CiAgICAtIHBvcnQ6IDgwODAKICAgICAgbmFtZTogaHR0cAogICAgICB0YXJnZXRQb3J0OiA4MDgwCi0gYXBpVmVyc2lvbjogdjEKICBraW5kOiBTZWNyZXQKICBtZXRhZGF0YToKICAgIG5hbWU6IGFwaWtleS12aWItdGVzdHMKICBkYXRhOgogICAga29uZ0NyZWRUeXBlOiBhMlY1TFdGMWRHZz0KICAgIGtleTogUTI5dGNHeHBZMkYwWldSUVlYTnpkMjl5WkRFeU15RTAKLSBhcGlWZXJzaW9uOiBjb25maWd1cmF0aW9uLmtvbmdocS5jb20vdjEKICBraW5kOiBLb25nQ29uc3VtZXIKICBtZXRhZGF0YToKICAgIG5hbWU6IHZpYi10ZXN0cwogICAgYW5ub3RhdGlvbnM6CiAgICAgIGt1YmVybmV0ZXMuaW8vaW5ncmVzcy5jbGFzczoga29uZwogIHVzZXJuYW1lOiAidmliLXRlc3RzIgogIGNyZWRlbnRpYWxzOgogIC0gYXBpa2V5LXZpYi10ZXN0cwotIGFwaVZlcnNpb246IGNvbmZpZ3VyYXRpb24ua29uZ2hxLmNvbS92MQogIGtpbmQ6IEtvbmdQbHVnaW4KICBtZXRhZGF0YToKICAgIG5hbWU6IGF1dGgtdmliLXRlc3RzCiAgcGx1Z2luOiBrZXktYXV0aAotIGFwaVZlcnNpb246IG5ldHdvcmtpbmcuazhzLmlvL3YxCiAga2luZDogSW5ncmVzcwogIG1ldGFkYXRhOgogICAgbmFtZTogdmliLXRlc3RzCiAgICBhbm5vdGF0aW9uczoKICAgICAga29uZ2hxLmNvbS9zdHJpcC1wYXRoOiAidHJ1ZSIKICAgICAga29uZ2hxLmNvbS9wbHVnaW5zOiBhdXRoLXZpYi10ZXN0cwogIHNwZWM6CiAgICBpbmdyZXNzQ2xhc3NOYW1lOiBrb25nCiAgICBydWxlczoKICAgIC0gaG9zdDogd3d3LmV4YW1wbGUuY29tCiAgICAgIGh0dHA6CiAgICAgICAgcGF0aHM6CiAgICAgICAgLSBwYXRoOiAvbmdpbngKICAgICAgICAgIHBhdGhUeXBlOiBJbXBsZW1lbnRhdGlvblNwZWNpZmljCiAgICAgICAgICBiYWNrZW5kOgogICAgICAgICAgICBzZXJ2aWNlOgogICAgICAgICAgICAgIG5hbWU6IG5naW54LXZpYi10ZXN0cwogICAgICAgICAgICAgIHBvcnQ6CiAgICAgICAgICAgICAgICBudW1iZXI6IDgwODA=", "target_platform": { "target_platform_id": "{VIB_ENV_ALTERNATIVE_TARGET_PLATFORM}", "size": { @@ -36,6 +36,35 @@ "params": { "endpoint": "lb-kong-http-proxy" } + }, + { + "action_id": "goss", + "params": { + "resources": { + "path": "/.vib/kong/goss" + }, + "remote": { + "workload": "deploy-kong" + }, + "vars_file": "vars.yaml" + } + }, + { + "action_id": "cypress", + "params": { + "resources": { + "path": "/.vib/kong/cypress" + }, + "endpoint": "lb-kong-http-proxy", + "app_protocol": "HTTP", + "env": { + "apikey": "ComplicatedPassword123!4", + "ingressHost": "www.example.com", + "ingressPath": "/nginx", + "externalIp": "{{ TARGET_IP }}", + "adminHttpPort": "443" + } + } } ] }, diff --git a/.vib/kong/vib-verify.json b/.vib/kong/vib-verify.json index faff44c0d1..e6d4815873 100644 --- a/.vib/kong/vib-verify.json +++ b/.vib/kong/vib-verify.json @@ -22,7 +22,7 @@ "url": "{SHA_ARCHIVE}", "path": "/bitnami/kong" }, - "runtime_parameters": "InBvZEFmZmluaXR5UHJlc2V0IjogImhhcmQiCiJwb2RBbnRpQWZmaW5pdHlQcmVzZXQiOiAiIgoicG9zdGdyZXNxbCI6CiAgInBvc3RncmVzcWxQYXNzd29yZCI6ICI3ZE14TGZjcXhOIgoicmVwbGljYUNvdW50IjogMQoic2VydmljZSI6CiAgInByb3h5SHR0cFBvcnQiOiA4MAogICJ0eXBlIjogIkxvYWRCYWxhbmNlciI=", + "runtime_parameters": "cmVwbGljYUNvdW50OiAxCmRhdGFiYXNlOiBwb3N0Z3Jlc3FsCmNvbnRhaW5lclNlY3VyaXR5Q29udGV4dDoKICBlbmFibGVkOiB0cnVlCiAgcnVuQXNVc2VyOiAxMDAyCmtvbmc6CiAgY29udGFpbmVyUG9ydHM6IAogICAgcHJveHlIdHRwOiA4MDAwCiAgICBwcm94eUh0dHBzOiA4NDQzCiAgICBhZG1pbkh0dHA6IDgwMDEKICAgIGFkbWluSHR0cHM6IDg0NDQKc2VydmljZToKICB0eXBlOiBMb2FkQmFsYW5jZXIKICBleHBvc2VBZG1pbjogdHJ1ZQogIGRpc2FibGVIdHRwUG9ydDogZmFsc2UKICBwb3J0czoKICAgIHByb3h5SHR0cDogODAKICAgIHByb3h5SHR0cHM6IDg0NDMKICAgIGFkbWluSHR0cDogNDQzCiAgICBhZG1pbkh0dHBzOiA4NDQ0CmluZ3Jlc3NDb250cm9sbGVyOgogIGVuYWJsZWQ6IHRydWUKICBpbmdyZXNzQ2xhc3M6IGtvbmcKcG9zdGdyZXNxbDoKICBlbmFibGVkOiB0cnVlCiAgYXV0aDoKICAgIHVzZXJuYW1lOiBrb25nCiAgICBwYXNzd29yZDogIiIKICAgIGRhdGFiYXNlOiBrb25nCmV4dHJhRGVwbG95OgotIGFwaVZlcnNpb246IGFwcHMvdjEKICBraW5kOiBEZXBsb3ltZW50CiAgbWV0YWRhdGE6CiAgICBuYW1lOiBuZ2lueC12aWItdGVzdHMKICBzcGVjOgogICAgcmVwbGljYXM6IDEKICAgIHNlbGVjdG9yOgogICAgICBtYXRjaExhYmVsczoKICAgICAgICBhcHA6IG5naW54CiAgICB0ZW1wbGF0ZToKICAgICAgbWV0YWRhdGE6CiAgICAgICAgbGFiZWxzOgogICAgICAgICAgYXBwOiBuZ2lueAogICAgICBzcGVjOgogICAgICAgIGNvbnRhaW5lcnM6CiAgICAgICAgLSBuYW1lOiBuZ2lueAogICAgICAgICAgaW1hZ2U6IGJpdG5hbWkvbmdpbngKICAgICAgICAgIHBvcnRzOgogICAgICAgICAgLSBjb250YWluZXJQb3J0OiA4MDgwCi0gYXBpVmVyc2lvbjogdjEKICBraW5kOiBTZXJ2aWNlCiAgbWV0YWRhdGE6CiAgICBuYW1lOiBuZ2lueC12aWItdGVzdHMKICAgIGxhYmVsczoKICAgICAgYXBwOiBuZ2lueAogIHNwZWM6CiAgICBzZWxlY3RvcjoKICAgICAgYXBwOiBuZ2lueAogICAgcG9ydHM6CiAgICAtIHBvcnQ6IDgwODAKICAgICAgbmFtZTogaHR0cAogICAgICB0YXJnZXRQb3J0OiA4MDgwCi0gYXBpVmVyc2lvbjogdjEKICBraW5kOiBTZWNyZXQKICBtZXRhZGF0YToKICAgIG5hbWU6IGFwaWtleS12aWItdGVzdHMKICBkYXRhOgogICAga29uZ0NyZWRUeXBlOiBhMlY1TFdGMWRHZz0KICAgIGtleTogUTI5dGNHeHBZMkYwWldSUVlYTnpkMjl5WkRFeU15RTAKLSBhcGlWZXJzaW9uOiBjb25maWd1cmF0aW9uLmtvbmdocS5jb20vdjEKICBraW5kOiBLb25nQ29uc3VtZXIKICBtZXRhZGF0YToKICAgIG5hbWU6IHZpYi10ZXN0cwogICAgYW5ub3RhdGlvbnM6CiAgICAgIGt1YmVybmV0ZXMuaW8vaW5ncmVzcy5jbGFzczoga29uZwogIHVzZXJuYW1lOiAidmliLXRlc3RzIgogIGNyZWRlbnRpYWxzOgogIC0gYXBpa2V5LXZpYi10ZXN0cwotIGFwaVZlcnNpb246IGNvbmZpZ3VyYXRpb24ua29uZ2hxLmNvbS92MQogIGtpbmQ6IEtvbmdQbHVnaW4KICBtZXRhZGF0YToKICAgIG5hbWU6IGF1dGgtdmliLXRlc3RzCiAgcGx1Z2luOiBrZXktYXV0aAotIGFwaVZlcnNpb246IG5ldHdvcmtpbmcuazhzLmlvL3YxCiAga2luZDogSW5ncmVzcwogIG1ldGFkYXRhOgogICAgbmFtZTogdmliLXRlc3RzCiAgICBhbm5vdGF0aW9uczoKICAgICAga29uZ2hxLmNvbS9zdHJpcC1wYXRoOiAidHJ1ZSIKICAgICAga29uZ2hxLmNvbS9wbHVnaW5zOiBhdXRoLXZpYi10ZXN0cwogIHNwZWM6CiAgICBpbmdyZXNzQ2xhc3NOYW1lOiBrb25nCiAgICBydWxlczoKICAgIC0gaG9zdDogd3d3LmV4YW1wbGUuY29tCiAgICAgIGh0dHA6CiAgICAgICAgcGF0aHM6CiAgICAgICAgLSBwYXRoOiAvbmdpbngKICAgICAgICAgIHBhdGhUeXBlOiBJbXBsZW1lbnRhdGlvblNwZWNpZmljCiAgICAgICAgICBiYWNrZW5kOgogICAgICAgICAgICBzZXJ2aWNlOgogICAgICAgICAgICAgIG5hbWU6IG5naW54LXZpYi10ZXN0cwogICAgICAgICAgICAgIHBvcnQ6CiAgICAgICAgICAgICAgICBudW1iZXI6IDgwODA=", "target_platform": { "target_platform_id": "{VIB_ENV_ALTERNATIVE_TARGET_PLATFORM}", "size": { @@ -36,6 +36,35 @@ "params": { "endpoint": "lb-kong-http-proxy" } + }, + { + "action_id": "goss", + "params": { + "resources": { + "path": "/.vib/kong/goss" + }, + "remote": { + "workload": "deploy-kong" + }, + "vars_file": "vars.yaml" + } + }, + { + "action_id": "cypress", + "params": { + "resources": { + "path": "/.vib/kong/cypress" + }, + "endpoint": "lb-kong-http-proxy", + "app_protocol": "HTTP", + "env": { + "apikey": "ComplicatedPassword123!4", + "ingressHost": "www.example.com", + "ingressPath": "/nginx", + "externalIp": "{{ TARGET_IP }}", + "adminHttpPort": "443" + } + } } ] }