Skip to content

Commit 16aa5b4

Browse files
committed
Add new AL2 based image and gunicorn
1 parent 4cf044c commit 16aa5b4

12 files changed

+803
-713
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ ENV/
102102
.mypy_cache/
103103

104104
# jwt keys
105-
keys
106105
tests/resources/keys/*.pem
107106

108107
.DS_Store

.secrets.baseline

+7-34
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,13 @@
115115
}
116116
],
117117
"results": {
118-
".github/workflows/ci.yaml": [
118+
".github/workflows/buildpipeline.yaml": [
119119
{
120120
"type": "Secret Keyword",
121-
"filename": ".github/workflows/ci.yaml",
121+
"filename": ".github/workflows/buildpipeline.yaml",
122122
"hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0",
123123
"is_verified": false,
124-
"line_number": 13
124+
"line_number": 17
125125
}
126126
],
127127
"deployment/scripts/postgresql/postgresql_init.sql": [
@@ -210,22 +210,13 @@
210210
"line_number": 137
211211
}
212212
],
213-
"fence/resources/storage/storageclient/cleversafe.py": [
214-
{
215-
"type": "Secret Keyword",
216-
"filename": "fence/resources/storage/storageclient/cleversafe.py",
217-
"hashed_secret": "7cb6efb98ba5972a9b5090dc2e517fe14d12cb04",
218-
"is_verified": false,
219-
"line_number": 274
220-
}
221-
],
222213
"fence/utils.py": [
223214
{
224215
"type": "Secret Keyword",
225216
"filename": "fence/utils.py",
226217
"hashed_secret": "8318df9ecda039deac9868adf1944a29a95c7114",
227218
"is_verified": false,
228-
"line_number": 129
219+
"line_number": 128
229220
}
230221
],
231222
"migrations/versions/a04a70296688_non_unique_client_name.py": [
@@ -268,14 +259,14 @@
268259
"filename": "tests/conftest.py",
269260
"hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9",
270261
"is_verified": false,
271-
"line_number": 1570
262+
"line_number": 1556
272263
},
273264
{
274265
"type": "Base64 High Entropy String",
275266
"filename": "tests/conftest.py",
276267
"hashed_secret": "227dea087477346785aefd575f91dd13ab86c108",
277268
"is_verified": false,
278-
"line_number": 1594
269+
"line_number": 1579
279270
}
280271
],
281272
"tests/credentials/google/test_credentials.py": [
@@ -394,24 +385,6 @@
394385
"line_number": 300
395386
}
396387
],
397-
"tests/storageclient/storage_client_mock.py": [
398-
{
399-
"type": "Secret Keyword",
400-
"filename": "tests/storageclient/storage_client_mock.py",
401-
"hashed_secret": "37bbea9557f9efd1eeadb25dda9ab6514f08fde9",
402-
"is_verified": false,
403-
"line_number": 158
404-
}
405-
],
406-
"tests/storageclient/test_cleversafe_api_client.py": [
407-
{
408-
"type": "Secret Keyword",
409-
"filename": "tests/storageclient/test_cleversafe_api_client.py",
410-
"hashed_secret": "f683c485d521c2e45830146dd570111770baea29",
411-
"is_verified": false,
412-
"line_number": 130
413-
}
414-
],
415388
"tests/test-fence-config.yaml": [
416389
{
417390
"type": "Basic Auth Credentials",
@@ -422,5 +395,5 @@
422395
}
423396
]
424397
},
425-
"generated_at": "2024-08-22T19:43:39Z"
398+
"generated_at": "2023-10-20T20:37:17Z"
426399
}

Dockerfile

+82-52
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,86 @@
1-
# To run: docker run --rm -d -v /path/to/fence-config.yaml:/var/www/fence/fence-config.yaml --name=fence -p 80:80 fence
2-
# To check running container do: docker exec -it fence /bin/bash
1+
ARG AZLINUX_BASE_VERSION=master
32

4-
FROM quay.io/cdis/python:python3.9-buster-2.0.0
3+
# Base stage with python-build-base
4+
FROM quay.io/cdis/python-build-base:${AZLINUX_BASE_VERSION} as base
5+
6+
# Comment this in, and comment out the line above, if quay is down
7+
# FROM 707767160287.dkr.ecr.us-east-1.amazonaws.com/gen3/python-build-base:${AZLINUX_BASE_VERSION} as base
58

69
ENV appname=fence
10+
ENV POETRY_NO_INTERACTION=1 \
11+
POETRY_VIRTUALENVS_IN_PROJECT=1 \
12+
POETRY_VIRTUALENVS_CREATE=1
13+
14+
WORKDIR /${appname}
15+
16+
# create gen3 user
17+
# Create a group 'gen3' with GID 1000 and a user 'gen3' with UID 1000
18+
RUN groupadd -g 1000 gen3 && \
19+
useradd -m -s /bin/bash -u 1000 -g gen3 gen3 && \
20+
chown -R gen3:gen3 /$appname && \
21+
mkdir -p /var/www/$appname && \
22+
chown -R gen3:gen3 /var/www/$appname && \
23+
chown -R gen3:gen3 /venv
24+
25+
26+
# Builder stage
27+
FROM base as builder
28+
29+
USER gen3
30+
31+
32+
RUN python -m venv /venv
33+
34+
35+
COPY poetry.lock pyproject.toml /${appname}/
36+
37+
RUN pip install poetry && \
38+
poetry install -vv --only main --no-interaction
39+
40+
COPY --chown=gen3:gen3 . /$appname
41+
COPY --chown=gen3:gen3 ./deployment/wsgi/wsgi.py /$appname/wsgi.py
42+
43+
# Run poetry again so this app itself gets installed too
44+
RUN poetry install --without dev --no-interaction
45+
46+
RUN git config --global --add safe.directory /${appname} && COMMIT=`git rev-parse HEAD` && echo "COMMIT=\"${COMMIT}\"" > /$appname/version_data.py \
47+
&& VERSION=`git describe --always --tags` && echo "VERSION=\"${VERSION}\"" >> /$appname/version_data.py
48+
49+
# Final stage
50+
FROM base
51+
52+
COPY --from=builder /venv /venv
53+
COPY --from=builder /$appname /$appname
54+
55+
# install tar
56+
RUN yum install tar -y
57+
58+
# install nginx
59+
RUN yum install nginx -y
60+
61+
RUN setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx
62+
63+
# chown nginx directories
64+
RUN chown -R gen3:gen3 /var/log/nginx
65+
66+
# pipe nginx logs to stdout and stderr
67+
RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
68+
69+
# create /var/lib/nginx/tmp/client_body to allow nginx to write to fence
70+
RUN mkdir -p /var/lib/nginx/tmp/client_body
71+
RUN chown -R gen3:gen3 /var/lib/nginx/
72+
73+
# copy nginx config
74+
COPY ./deployment/nginx/nginx.conf /etc/nginx/nginx.conf
75+
76+
77+
# Switch to non-root user 'gen3' for the serving process
78+
USER gen3
79+
80+
RUN source /venv/bin/activate
81+
82+
ENV PYTHONUNBUFFERED=1 \
83+
PYTHONIOENCODING=UTF-8
84+
785

8-
RUN pip install --upgrade pip
9-
RUN pip install --upgrade poetry
10-
RUN apt-get update \
11-
&& apt-get install -y --no-install-recommends curl bash git \
12-
&& apt-get -y install vim \
13-
libmcrypt4 mcrypt \
14-
&& apt-get clean \
15-
&& rm -rf /var/lib/apt/lists/
16-
17-
RUN mkdir -p /var/www/$appname \
18-
&& mkdir -p /var/www/.cache/Python-Eggs/ \
19-
&& mkdir /run/nginx/ \
20-
&& ln -sf /dev/stdout /var/log/nginx/access.log \
21-
&& ln -sf /dev/stderr /var/log/nginx/error.log \
22-
&& chown nginx -R /var/www/.cache/Python-Eggs/ \
23-
&& chown nginx /var/www/$appname
24-
25-
# aws cli v2 - needed for storing files in s3 during usersync k8s job
26-
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
27-
&& unzip awscliv2.zip \
28-
&& ./aws/install \
29-
&& /bin/rm -rf awscliv2.zip ./aws
30-
31-
WORKDIR /$appname
32-
33-
# copy ONLY poetry artifact, install the dependencies but not fence
34-
# this will make sure than the dependencies is cached
35-
COPY poetry.lock pyproject.toml /$appname/
36-
RUN poetry config virtualenvs.create false \
37-
&& poetry install -vv --no-root --no-dev --no-interaction \
38-
&& poetry show -v
39-
40-
# copy source code ONLY after installing dependencies
41-
COPY . /$appname
42-
COPY ./deployment/uwsgi/uwsgi.ini /etc/uwsgi/uwsgi.ini
43-
COPY ./deployment/uwsgi/wsgi.py /$appname/wsgi.py
44-
COPY clear_prometheus_multiproc /$appname/clear_prometheus_multiproc
45-
46-
# install fence
47-
RUN poetry config virtualenvs.create false \
48-
&& poetry install -vv --no-dev --no-interaction \
49-
&& poetry show -v
50-
51-
RUN COMMIT=`git rev-parse HEAD` && echo "COMMIT=\"${COMMIT}\"" >$appname/version_data.py \
52-
&& VERSION=`git describe --always --tags` && echo "VERSION=\"${VERSION}\"" >>$appname/version_data.py
53-
54-
WORKDIR /var/www/$appname
55-
56-
CMD ["sh","-c","bash /fence/dockerrun.bash && /dockerrun.sh"]
86+
CMD ["/fence/dockerrun.bash"]

deployment/nginx/nginx.conf

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
user gen3;
2+
worker_processes auto;
3+
error_log /var/log/nginx/error.log notice;
4+
pid /var/lib/nginx/nginx.pid;
5+
6+
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
7+
include /usr/share/nginx/modules/*.conf;
8+
9+
events {
10+
worker_connections 1024;
11+
}
12+
13+
http {
14+
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
15+
'$status $body_bytes_sent "$http_referer" '
16+
'"$http_user_agent" "$http_x_forwarded_for"';
17+
18+
access_log /var/log/nginx/access.log main;
19+
20+
sendfile on;
21+
tcp_nopush on;
22+
keepalive_timeout 65;
23+
types_hash_max_size 4096;
24+
25+
include /etc/nginx/mime.types;
26+
default_type application/octet-stream;
27+
28+
# Load modular configuration files from the /etc/nginx/conf.d directory.
29+
# See http://nginx.org/en/docs/ngx_core_module.html#include
30+
# for more information.
31+
include /etc/nginx/conf.d/*.conf;
32+
33+
server {
34+
35+
listen 80;
36+
server_name localhost;
37+
38+
location / {
39+
proxy_pass http://127.0.0.1:8000;
40+
proxy_set_header Host $host;
41+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
42+
}
43+
}
44+
}

deployment/uwsgi/uwsgi.ini

-37
This file was deleted.

deployment/wsgi/gunicorn.conf.py

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
wsgi_app = "deployment.wsgi.wsgi:application"
2+
bind = "0.0.0.0:8000"
3+
workers = 4
4+
preload_app = True
5+
user = "gen3"
6+
group = "gen3"
7+
timeout = 300
8+
keepalive = 2
9+
keepalive_timeout = 5
File renamed without changes.

dockerrun.bash

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Update certificate authority index -
55
# environment may have mounted more authorities
66
#
7-
update-ca-certificates
7+
# update-ca-certificates
88
#
99
# Kubernetes may mount jwt-keys as a tar ball
1010
#
@@ -15,6 +15,9 @@ if [ -f /fence/jwt-keys.tar ]; then
1515
if [ -d jwt-keys ]; then
1616
mkdir -p keys
1717
mv jwt-keys/* keys/
18+
rm -rf /fence/keys/key/
1819
fi
1920
)
2021
fi
22+
nginx
23+
gunicorn -c /fence/deployment/wsgi/gunicorn.conf.py

fence/jwt/keys.py

+17-4
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,26 @@ def from_directory(cls, keys_dir, naming_function=None):
148148
prv_filepath = os.path.join(keys_dir, "jwt_private_key.pem")
149149

150150
if not os.path.isfile(pub_filepath):
151-
raise EnvironmentError(
152-
"missing public key file; expected file to exist: " + pub_filepath
153-
)
151+
# Generate public key from private key
152+
with open(prv_filepath, "r") as f:
153+
private_key_file = f.read()
154+
private_key = serialization.load_pem_private_key(
155+
bytes(private_key_file, "utf-8"),
156+
password=None,
157+
backend=default_backend(),
158+
)
159+
public_key = private_key.public_key()
160+
public_key = public_key.public_bytes(
161+
encoding=serialization.Encoding.PEM,
162+
format=serialization.PublicFormat.SubjectPublicKeyInfo,
163+
)
164+
public_key = public_key.decode("utf-8")
165+
with open(pub_filepath, "w") as f:
166+
f.write(public_key)
154167

155168
if not os.path.isfile(prv_filepath):
156169
raise EnvironmentError(
157-
"missing public key file; expected file to exist: " + prv_filepath
170+
"missing private key file; expected file to exist: " + prv_filepath
158171
)
159172

160173
with open(pub_filepath, "r") as f:

keys/key/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Need this folder for permission reasons inside the container

0 commit comments

Comments
 (0)