Skip to content

Commit 8e54635

Browse files
committed
Merge pull request #18
1. Added definition of a pouta VM with a kind cluster to host a dev/test environment 2. Converted k8s yaml's into a helm chart 3. Adjusted the ansible playbook to work nicely with the dev/test environment
2 parents ba2754d + 456930f commit 8e54635

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1287
-421
lines changed

.git-crypt/.gitattributes

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Do not edit this file. To specify the files to encrypt, create your own
2+
# .gitattributes file in the directory where your files are.
3+
* !filter !diff
4+
*.gpg binary
Binary file not shown.

.gitattributes

+2
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ client/container_preparation/input_logic/age filter=lfs diff=lfs merge=lfs -text
22
client/container_preparation/input_logic/curl filter=lfs diff=lfs merge=lfs -text
33
client/container_preparation/input_logic/jq filter=lfs diff=lfs merge=lfs -text
44
client/container_preparation/input_logic/tar filter=lfs diff=lfs merge=lfs -text
5+
# encrypted terraform secrets
6+
terraform/secrets/** filter=git-crypt diff=git-crypt

.github/workflows/build-container-prep-image.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
name: Build and publish HPCS container preparation image
2-
on: [push]
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
37

48
env:
59
IMAGE_NAME: hpcs/container-prep

.github/workflows/build-data-prep-image.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
name: Build and publish HPCS data preparation image
2-
on: [push]
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
37

48
env:
59
IMAGE_NAME: hpcs/data-prep

.github/workflows/build-job-prep-image.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
name: Build and publish HPCS job preparation image
2-
on: [push]
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
37

48
env:
59
IMAGE_NAME: hpcs/job-prep

.github/workflows/build-server-image.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
name: Build and publish HPCS server image
2-
on: [push]
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
37

48
env:
59
IMAGE_NAME: hpcs/server

.github/workflows/general-lint.yaml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Build and publish HPCS server image
2+
on:
3+
push:
4+
branches:
5+
- main
6+
pull_request:
7+
8+
jobs:
9+
general_lint:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v2
13+
- name: Checking for newlines at the end of files
14+
run: if (for file in $(find . -type f -not -path './.git/*' -not -path './.git-crypt/*' -not -path './terraform/secrets/*') ; do [ "$(tail -c 1 < "${file}")" == "" ] || echo "${file} has no newline at the end..." ; done) | grep . ; then exit 1 ; fi
15+
- name: Checking for trailing whitespaces
16+
run: if find . -type f -not -path './.git/*' -exec egrep -l " +$" {} \; | grep . ; then exit 1 ; fi
17+
18+
- name: Running shellcheck on *.sh files
19+
run: |
20+
find . -name .git -type d -prune -o -type f -name \*.sh -print0 |
21+
xargs -0 -r -n1 shellcheck
22+
helm_lint:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v2
26+
- name: run helm lint on hpcs-stack
27+
run: docker run --rm -v $(pwd)/k8s:/apps alpine/helm:latest lint hpcs-stack
28+
terraform_lint:
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v2
32+
- name: run terraform fmt
33+
run: docker run --rm -v $(pwd):/data docker.io/hashicorp/terraform fmt -check /data/terraform

.gitignore

+16
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,19 @@
1010

1111
# Undo-tree save-files
1212
*.~undo-tree
13+
14+
# openrc configs
15+
*-openrc.sh
16+
17+
# terraform
18+
.terraform*
19+
## local variables
20+
terraform/*.tfvars
21+
## user specific secrets
22+
terraform/secrets/public_keys
23+
terraform/secrets/tunnel_keys
24+
25+
# Ignore certificates and keys
26+
*.crt
27+
*.csr
28+
*.key

README.md

+27-105
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ To run one of the containers :
191191
docker compose run --rm [data/container/job]-prep
192192
```
193193

194-
If you want to run the whole process by yourself :
194+
If you want to run the whole process by yourself :
195195

196196
```bash
197197
docker compose run --rm data-prep
@@ -203,9 +203,10 @@ An example demonstration is available [here](https://asciinema.org/a/PWDzxlaVQmf
203203

204204
### Server
205205

206-
HPCS Server is an API, interfacing HPCS client with Vault and Spire. This section needs basic knowledge of [SPIFFE/SPIRE](https://spiffe.io/) and [HashiCorp Vault](https://www.vaultproject.io/).
206+
HPCS Server is an API, interfacing HPCS client with Vault and Spire. This section needs basic knowledge of [SPIFFE/SPIRE](https://spiffe.io/) and [HashiCorp Vault](https://www.vaultproject.io/).
207207

208208
For k8s, we only consider `kubectl` and `ansible` as available tools and that `kubectl` can create pods. Vault roles, spire identities are created automatically.
209+
For development and demonstrative purposes we provide a `terraform` definition of a VM with an operational kubernetes cluster, for documentation and deployment instructions go [there](terraform).
209210

210211
For docker-compose, we consider the Vault and the Spire Server as setup and the Spire-OIDC provider implemented to allow login to the vault using SVID identity. We also consider that proper roles are created in Vault to authorize HPCS Server to write roles and policies to the Vault, using a server SPIFFEID.
211212

@@ -257,77 +258,29 @@ Before proceeding to HPCS' deployment, an original setup is required including :
257258
- A ready-to-run k8s cluster
258259
- `kubectl` and `helm` available and able to run kubernetes configurations (`.yaml`)
259260
- `rbac`, `storage` and `dns` and `helm` kubernetes capabilities, f.e : `microk8s enable rbac storage dns helm` with microk8s.
260-
261+
261262
Please note down the name of your k8s cluster in order to run later deployments.
262263

263264
##### Configuration
264265

265-
Several configurations are to be reviewed before proceeding.
266-
- Nginx SSL Certificate path : Please review in `/k8s/spire-server-nginx-configmap.yaml` (section `ssl_certificate`) and `/k8s/spire-server-statefulset.yaml` (section `volumeMounts` of container `hpcs-nginx` and section `volumes` of the pod configuration). If you plan to run the deployment using ansible, please review `/k8s/deploy-all.yaml`, section `Copy oidc cert to vault's pod` and `Create spire-oidc {key, csr, cert}` for the host path to the certificate. Create the directory configured before running deployment.
267-
268-
- Cluster name : Please review in `/k8s/hpcs-server-configmap.yaml`, section "`agent.conf`", then "`k8s_psat`" and `/k8s/spire-server-configmap.yaml`, section "`server.conf`", then "`k8s_psat`", replace "`docker-desktop`" with your k8s cluster name.
269-
270-
- For further information about spire agent/ server configurations under `/k8s/hpcs-server-configmap.yaml` and `/k8s/spire-server-configmap.yaml`, please refer to spire-server [configuration reference](https://spiffe.io/docs/latest/deploying/spire_server) and spire-agent [configuration reference](https://spiffe.io/docs/latest/deploying/spire_agent/).
271-
272-
273266
##### Bash
274267

275268
This part of the documentation walks you through the different steps necessary in order to run a manual deployment of HPCS' serverside (including Vault, Spire-Server and HPCS Server).
276269

277-
__Starting with the "`spire-server`" pods :__
278-
279-
Generate your nginx certificate :
280-
```bash
281-
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /path/to/your/privatekey.key -out /path/to/your/certificate.crt -addext "subjectAltName = DNS:spire-oidc"
282-
```
283-
284-
Create HPCS namespace :
285-
```bash
286-
cd k8s
287-
kubectl apply -f hpcs-namespace.yaml
288-
```
289-
290-
Create Spire service account and cluster role :
291-
```bash
292-
kubectl apply -f spire-server-account.yaml -f spire-server-cluster-role.yaml
293-
```
294-
295-
Create configmaps for spire-server, spire-oidc and nginx proxy :
270+
Generate your certificate :
296271
```bash
297-
kubectl apply -f spire-oidc-configmap.yaml -f spire-server-configmap.yaml -f spire-server-nginx-configmap.yaml
272+
openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout hpcs-stack/charts/spire/files/spire-oidc.key -out hpcs-stack/charts/spire/files/spire-oidc.crt -addext "subjectAltName = DNS:spire-oidc"
298273
```
299274

300-
Create spire-server statefulset, managing spire-server-x pods :
301-
```bash
302-
kubectl apply -f spire-server-statefulset.yaml
303-
```
304-
305-
Expose spire-oidc proxy and spire-server's api over the cluster :
306-
```bash
307-
kubectl apply -f spire-server-service.yaml -f spire-oidc-service.yaml
308-
```
309-
310-
At this point, you should be able to see at least one `spire-server-x` pod, f.e :
311-
275+
Add hashicorp repo and run installation :
312276
```bash
313-
kubectl get -n hpcs pod/spire-server-0
314-
NAME READY STATUS RESTARTS AGE
315-
spire-server-0 3/3 Running 0 30s
277+
helm repo add hashicorp https://helm.releases.hashicorp.com
278+
helm install vault hashicorp/vault --version 0.27.0 --namespace=hpcs
316279
```
317280

318-
And the port on which the spire-server API is exposed (here 31140) :
281+
Install `hpcs-stack` chart :
319282
```bash
320-
kubectl get -n hpcs service/spire-server
321-
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
322-
spire-server LoadBalancer 10.99.214.248 localhost 8081:31140/TCP 30s
323-
```
324-
325-
__Then install Hashicorp Vault via it's official helm chart (here with microk8s):__
326-
327-
Add hashicorp repo and run installation :
328-
```bash
329-
microk8s helm3 repo add hashicorp https://helm.releases.hashicorp.com
330-
helm install vault hashicorp/vault --version 0.27.0 --namespace=hpcs
283+
helm upgrade --install --namespace hpcs --create-namespace hpcs-stack $(git rev-parse --show-toplevel)/k8s/hpcs-stack
331284
```
332285

333286
Initialize the Vault :
@@ -341,7 +294,14 @@ Unseal vault :
341294
kubectl exec -it vault-0 -n hpcs -- vault operator unseal [seal token]
342295
```
343296

344-
Connect to the vault to enable jwt auth and kvv2 secrets, register oidc as a source :
297+
Now double check that `spire-server` installed as part of `hpcs-stack` is actually ready already :
298+
```bash
299+
-> kubectl get --namespace hpcs pods/spire-server-0
300+
NAME READY STATUS RESTARTS AGE
301+
spire-server-0 3/3 Running 0 73m
302+
```
303+
304+
If it's ready you can connect to the vault to enable jwt auth and kvv2 secrets, register oidc as a source :
345305
```bash
346306
kubectl exec -it vault-0 -n hpcs -- sh
347307
export VAULT_TOKEN="[root token]"
@@ -360,17 +320,6 @@ vault write auth/jwt/config oidc_discovery_url=https://spire-oidc oidc_discovery
360320
"
361321
```
362322

363-
Expose Vault's API to the node :
364-
```bash
365-
kubectl expose service vault --name="vault-external" --type="NodePort" --target-port 8200 -n hpcs
366-
```
367-
368-
At this point, Vault is running and it's API is exposed, to check on which port, run :
369-
```bash
370-
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
371-
vault-external NodePort 10.111.198.147 localhost 8200:31819/TCP,8201:31587/TCP 2s
372-
```
373-
374323
__Next step is to create a spire identity and it's vault role in order to be able to identify HPCS-Server against Vault__
375324

376325
Get your kubernetes node uid (repeat this and the following spire identity creation for every nodes):
@@ -408,46 +357,19 @@ path "sys/policies/acl/*" {
408357
en_policies=hpcs-server
409358
```
410359

411-
__You can now deploy HPCS server__
412-
413-
Create hpcs-server and hpcs-spire service accounts :
414-
```bash
415-
kubectl apply -f hpcs-server-account.yaml -f hpcs-spire-account.yaml
416-
```
417-
418-
Create hpcs server configmap :
419-
```bash
420-
kubectl apply -f hpcs-server-configmap.yaml
421-
```
360+
You can now wait for HPCS server to finish setting up :
422361

423-
Create hpcs-server statefulset (and underlying pods) :
424362
```bash
425-
kubectl apply -f hpcs-server-statefulset.yaml
426-
```
427-
428-
Expose hpcs-server api over the cluster :
429-
```bash
430-
kubectl apply -f hpcs-server-service.yaml
431-
```
432-
433-
Expose hpcs-server service over the node :
434-
```bash
435-
kubectl expose service hpcs-server --name="hpcs-server-external" --type="NodePort" --target-port 10080 -n hpcs
436-
```
437-
438-
Check exposed port :
439-
```bash
440-
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
441-
hpcs-server-external NodePort 10.111.198.151 localhost 10080:31827/TCP 2s
363+
-> kubectl get --namespace hpcs pods/hpcs-server-0
364+
NAME READY STATUS RESTARTS AGE
365+
hpcs-server-0 1/1 Running 3 (75m ago) 75m
442366
```
443367

444368
That's it, you can now use HPCS server as you please.
445369

446370
##### Ansible
447371

448-
:warning: This method is currently still under development. You could run into non-documented issues.
449-
450-
The previously explained steps can be automatically run using an ansible playbook available under `/k8s/deploy-all.yaml`
372+
The previously explained steps can be automatically run using an ansible [playbook](k8s/deploy-all.yaml).
451373

452374
All the pre-requisites listed before are necessary to run this playbook. If you are running kubernetes using `microk8s`, you will need to create aliases or fake commands for `helm`, for example using a script :
453375
```bash
@@ -585,7 +507,7 @@ Using TPM, for example, it is very easy to run automatic node attestation, based
585507

586508
### Encrypted container
587509

588-
The goal of this project was to leverage Singularity/Apptainer's [encrypted containers](https://docs.sylabs.io/guides/3.4/user-guide/encryption.html). This feature enables the end user to protect the runtime of the container, allowing it to confine unencrypted data within the encrypted container, adding an extra layer of security.
510+
The goal of this project was to leverage Singularity/Apptainer's [encrypted containers](https://docs.sylabs.io/guides/3.4/user-guide/encryption.html). This feature enables the end user to protect the runtime of the container, allowing it to confine unencrypted data within the encrypted container, adding an extra layer of security.
589511

590512
Unfortunately for LUMI, this feature relies on different technologies, depending the permission level at which the container is encrypted, this behaviour is documented in the following table for usage on LUMI :
591513

@@ -599,7 +521,7 @@ Unfortunately for LUMI, this feature relies on different technologies, depending
599521
Two main reasons for the issues with the encrypted containers :
600522
- Cannot run as root on a node (no workaround, as this is a feature of HPC environments).
601523
- User namespaces are disabled on LUMI (for secure reason, [this stackexchange](https://security.stackexchange.com/questions/267628/user-namespaces-do-they-increase-security-or-introduce-new-attack-surface) has some explanations).
602-
524+
603525
To run encrypted containers as described above, we would need to enable user namespaces on the platform. This would require a thorough risk/benefit assessment, since it introduces new attack surfaces and therefore will not be introduced lightly, at least not on on LUMI in the near future.
604526

605527
We mitigate the unavailability of encrypted containers in two steps :
@@ -616,7 +538,7 @@ When a client wants to encrypt its data or container and to give access to it to
616538
- Client runs containers using cgroupsv2
617539
- Client runs on Linux
618540
- `spire-agent api fetch` can be attested using spire-agent binary's `sha256sum`
619-
- `python3 ./utils/spawn_agent.py` can't be attested since the `sha256sum` recognised by the workload API is `python3`'s. A mitigation to that would be to compile the code, if possible. This would potentially provide a unique binary that would then be able to be attested using `sha256sum`
541+
- `python3 ./utils/spawn_agent.py` can't be attested since the `sha256sum` recognised by the workload API is `python3`'s. A mitigation to that would be to compile the code, if possible. This would potentially provide a unique binary that would then be able to be attested using `sha256sum`
620542
- Client runs on MacOS
621543
- No attestation is doable at the moment since MacOS doesn't support docker and runs container inside of a Linux VM
622544
- Using cgroupsv2

client/container_preparation/Dockerfile

+20-18
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@
22
ARG BUILDPLATFORM=linux/amd64
33
FROM --platform=$BUILDPLATFORM python:3.9-alpine
44

5-
6-
7-
# Add rust binaries to PATH
8-
ENV PATH="$PATH:/root/.cargo/bin"
9-
105
# Create code directory, output directory
116
RUN mkdir /container_preparation /output
127

@@ -19,22 +14,29 @@ COPY ./utils /container_preparation/utils
1914
# Set workdir
2015
WORKDIR /container_preparation
2116

22-
# Install necessary packages, spire-agent and rust
17+
# Install necessary packages
2318
RUN apk add --no-cache \
24-
git=2.43.0-r0 \
25-
curl=8.5.0-r0 \
19+
git=2.45.2-r0 \
20+
curl=8.11.0-r2 \
2621
jq=1.7.1-r0 \
2722
build-base=0.5-r3 \
28-
libffi-dev=3.4.4-r3 && \
29-
curl -LsSf -o spire-1.9.0-linux-amd64-musl.tar.gz https://github.com/spiffe/spire/releases/download/v1.9.0/spire-1.9.0-linux-amd64-musl.tar.gz && \
30-
tar xvf spire-1.9.0-linux-amd64-musl.tar.gz ; mv spire-1.9.0 /opt ; mv /opt/spire-1.9.0 /opt/spire && \
31-
ln -s /opt/spire/bin/spire-agent /usr/bin/spire-agent && \
32-
ln -s /opt/spire/bin/spire-server /usr/bin/spire-server && \
33-
rm -rf spire-1.9.0-linux-amd64-musl.tar.gz && \
34-
curl https://sh.rustup.rs -sSf -o rustup.sh ; chmod +x rustup.sh ; ./rustup.sh -y ; export PATH="$PATH":/root/.cargo/bin && \
35-
pip install --no-cache-dir -r ./requirements.txt && \
36-
pip install --no-cache-dir git+https://github.com/HewlettPackard/py-spiffe.git@3640af9d6629c05e027f99010abc934cb74122a8 && \
37-
rm -r /root/.cargo /root/.rustup
23+
libffi-dev=3.4.6-r0
24+
# Install spire-agent
25+
RUN curl -LsSf -o spire-1.9.0-linux-amd64-musl.tar.gz https://github.com/spiffe/spire/releases/download/v1.9.0/spire-1.9.0-linux-amd64-musl.tar.gz && \
26+
tar xvf spire-1.9.0-linux-amd64-musl.tar.gz && \
27+
mv spire-1.9.0 /opt && \
28+
mv /opt/spire-1.9.0 /opt/spire && \
29+
ln -s /opt/spire/bin/spire-agent /usr/bin/spire-agent && \
30+
ln -s /opt/spire/bin/spire-server /usr/bin/spire-server && \
31+
rm -rf spire-1.9.0-linux-amd64-musl.tar.gz
32+
# Install python things (and rust temporarily)
33+
RUN curl https://sh.rustup.rs -sSf -o rustup.sh && \
34+
chmod +x rustup.sh && \
35+
./rustup.sh -y && \
36+
export PATH="$PATH:/root/.cargo/bin" && \
37+
pip install --no-cache-dir -r ./requirements.txt && \
38+
pip install --no-cache-dir git+https://github.com/HewlettPackard/py-spiffe.git@3640af9d6629c05e027f99010abc934cb74122a8 && \
39+
rm -r /root/.cargo /root/.rustup
3840

3941
# Set entrypoint
4042
ENTRYPOINT [ "./entrypoint.sh" ]

0 commit comments

Comments
 (0)