Skip to content

Commit

Permalink
Add new AL2 based image and gunicorn
Browse files Browse the repository at this point in the history
  • Loading branch information
jawadqur committed Sep 4, 2024
1 parent 4cf044c commit 16aa5b4
Show file tree
Hide file tree
Showing 12 changed files with 803 additions and 713 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ ENV/
.mypy_cache/

# jwt keys
keys
tests/resources/keys/*.pem

.DS_Store
Expand Down
41 changes: 7 additions & 34 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,13 @@
}
],
"results": {
".github/workflows/ci.yaml": [
".github/workflows/buildpipeline.yaml": [
{
"type": "Secret Keyword",
"filename": ".github/workflows/ci.yaml",
"filename": ".github/workflows/buildpipeline.yaml",
"hashed_secret": "3e26d6750975d678acb8fa35a0f69237881576b0",
"is_verified": false,
"line_number": 13
"line_number": 17
}
],
"deployment/scripts/postgresql/postgresql_init.sql": [
Expand Down Expand Up @@ -210,22 +210,13 @@
"line_number": 137
}
],
"fence/resources/storage/storageclient/cleversafe.py": [
{
"type": "Secret Keyword",
"filename": "fence/resources/storage/storageclient/cleversafe.py",
"hashed_secret": "7cb6efb98ba5972a9b5090dc2e517fe14d12cb04",
"is_verified": false,
"line_number": 274
}
],
"fence/utils.py": [
{
"type": "Secret Keyword",
"filename": "fence/utils.py",
"hashed_secret": "8318df9ecda039deac9868adf1944a29a95c7114",
"is_verified": false,
"line_number": 129
"line_number": 128
}
],
"migrations/versions/a04a70296688_non_unique_client_name.py": [
Expand Down Expand Up @@ -268,14 +259,14 @@
"filename": "tests/conftest.py",
"hashed_secret": "1348b145fa1a555461c1b790a2f66614781091e9",
"is_verified": false,
"line_number": 1570
"line_number": 1556
},
{
"type": "Base64 High Entropy String",
"filename": "tests/conftest.py",
"hashed_secret": "227dea087477346785aefd575f91dd13ab86c108",
"is_verified": false,
"line_number": 1594
"line_number": 1579
}
],
"tests/credentials/google/test_credentials.py": [
Expand Down Expand Up @@ -394,24 +385,6 @@
"line_number": 300
}
],
"tests/storageclient/storage_client_mock.py": [
{
"type": "Secret Keyword",
"filename": "tests/storageclient/storage_client_mock.py",
"hashed_secret": "37bbea9557f9efd1eeadb25dda9ab6514f08fde9",
"is_verified": false,
"line_number": 158
}
],
"tests/storageclient/test_cleversafe_api_client.py": [
{
"type": "Secret Keyword",
"filename": "tests/storageclient/test_cleversafe_api_client.py",
"hashed_secret": "f683c485d521c2e45830146dd570111770baea29",
"is_verified": false,
"line_number": 130
}
],
"tests/test-fence-config.yaml": [
{
"type": "Basic Auth Credentials",
Expand All @@ -422,5 +395,5 @@
}
]
},
"generated_at": "2024-08-22T19:43:39Z"
"generated_at": "2023-10-20T20:37:17Z"
}
134 changes: 82 additions & 52 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,56 +1,86 @@
# To run: docker run --rm -d -v /path/to/fence-config.yaml:/var/www/fence/fence-config.yaml --name=fence -p 80:80 fence
# To check running container do: docker exec -it fence /bin/bash
ARG AZLINUX_BASE_VERSION=master

FROM quay.io/cdis/python:python3.9-buster-2.0.0
# Base stage with python-build-base
FROM quay.io/cdis/python-build-base:${AZLINUX_BASE_VERSION} as base

# Comment this in, and comment out the line above, if quay is down
# FROM 707767160287.dkr.ecr.us-east-1.amazonaws.com/gen3/python-build-base:${AZLINUX_BASE_VERSION} as base

ENV appname=fence
ENV POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=1 \
POETRY_VIRTUALENVS_CREATE=1

WORKDIR /${appname}

# create gen3 user
# Create a group 'gen3' with GID 1000 and a user 'gen3' with UID 1000
RUN groupadd -g 1000 gen3 && \
useradd -m -s /bin/bash -u 1000 -g gen3 gen3 && \
chown -R gen3:gen3 /$appname && \
mkdir -p /var/www/$appname && \
chown -R gen3:gen3 /var/www/$appname && \
chown -R gen3:gen3 /venv


# Builder stage
FROM base as builder

USER gen3


RUN python -m venv /venv


COPY poetry.lock pyproject.toml /${appname}/

RUN pip install poetry && \
poetry install -vv --only main --no-interaction

COPY --chown=gen3:gen3 . /$appname
COPY --chown=gen3:gen3 ./deployment/wsgi/wsgi.py /$appname/wsgi.py

# Run poetry again so this app itself gets installed too
RUN poetry install --without dev --no-interaction

RUN git config --global --add safe.directory /${appname} && COMMIT=`git rev-parse HEAD` && echo "COMMIT=\"${COMMIT}\"" > /$appname/version_data.py \
&& VERSION=`git describe --always --tags` && echo "VERSION=\"${VERSION}\"" >> /$appname/version_data.py

# Final stage
FROM base

COPY --from=builder /venv /venv
COPY --from=builder /$appname /$appname

# install tar
RUN yum install tar -y

# install nginx
RUN yum install nginx -y

RUN setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx

# chown nginx directories
RUN chown -R gen3:gen3 /var/log/nginx

# pipe nginx logs to stdout and stderr
RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log

# create /var/lib/nginx/tmp/client_body to allow nginx to write to fence
RUN mkdir -p /var/lib/nginx/tmp/client_body
RUN chown -R gen3:gen3 /var/lib/nginx/

# copy nginx config
COPY ./deployment/nginx/nginx.conf /etc/nginx/nginx.conf


# Switch to non-root user 'gen3' for the serving process
USER gen3

RUN source /venv/bin/activate

ENV PYTHONUNBUFFERED=1 \
PYTHONIOENCODING=UTF-8


RUN pip install --upgrade pip
RUN pip install --upgrade poetry
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl bash git \
&& apt-get -y install vim \
libmcrypt4 mcrypt \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/

RUN mkdir -p /var/www/$appname \
&& mkdir -p /var/www/.cache/Python-Eggs/ \
&& mkdir /run/nginx/ \
&& ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log \
&& chown nginx -R /var/www/.cache/Python-Eggs/ \
&& chown nginx /var/www/$appname

# aws cli v2 - needed for storing files in s3 during usersync k8s job
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
&& unzip awscliv2.zip \
&& ./aws/install \
&& /bin/rm -rf awscliv2.zip ./aws

WORKDIR /$appname

# copy ONLY poetry artifact, install the dependencies but not fence
# this will make sure than the dependencies is cached
COPY poetry.lock pyproject.toml /$appname/
RUN poetry config virtualenvs.create false \
&& poetry install -vv --no-root --no-dev --no-interaction \
&& poetry show -v

# copy source code ONLY after installing dependencies
COPY . /$appname
COPY ./deployment/uwsgi/uwsgi.ini /etc/uwsgi/uwsgi.ini
COPY ./deployment/uwsgi/wsgi.py /$appname/wsgi.py
COPY clear_prometheus_multiproc /$appname/clear_prometheus_multiproc

# install fence
RUN poetry config virtualenvs.create false \
&& poetry install -vv --no-dev --no-interaction \
&& poetry show -v

RUN COMMIT=`git rev-parse HEAD` && echo "COMMIT=\"${COMMIT}\"" >$appname/version_data.py \
&& VERSION=`git describe --always --tags` && echo "VERSION=\"${VERSION}\"" >>$appname/version_data.py

WORKDIR /var/www/$appname

CMD ["sh","-c","bash /fence/dockerrun.bash && /dockerrun.sh"]
CMD ["/fence/dockerrun.bash"]
44 changes: 44 additions & 0 deletions deployment/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
user gen3;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/lib/nginx/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
worker_connections 1024;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
tcp_nopush on;
keepalive_timeout 65;
types_hash_max_size 4096;

include /etc/nginx/mime.types;
default_type application/octet-stream;

# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;

server {

listen 80;
server_name localhost;

location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
37 changes: 0 additions & 37 deletions deployment/uwsgi/uwsgi.ini

This file was deleted.

9 changes: 9 additions & 0 deletions deployment/wsgi/gunicorn.conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
wsgi_app = "deployment.wsgi.wsgi:application"
bind = "0.0.0.0:8000"
workers = 4
preload_app = True
user = "gen3"
group = "gen3"
timeout = 300
keepalive = 2
keepalive_timeout = 5
File renamed without changes.
5 changes: 4 additions & 1 deletion dockerrun.bash
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Update certificate authority index -
# environment may have mounted more authorities
#
update-ca-certificates
# update-ca-certificates
#
# Kubernetes may mount jwt-keys as a tar ball
#
Expand All @@ -15,6 +15,9 @@ if [ -f /fence/jwt-keys.tar ]; then
if [ -d jwt-keys ]; then
mkdir -p keys
mv jwt-keys/* keys/
rm -rf /fence/keys/key/
fi
)
fi
nginx
gunicorn -c /fence/deployment/wsgi/gunicorn.conf.py
21 changes: 17 additions & 4 deletions fence/jwt/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,26 @@ def from_directory(cls, keys_dir, naming_function=None):
prv_filepath = os.path.join(keys_dir, "jwt_private_key.pem")

if not os.path.isfile(pub_filepath):
raise EnvironmentError(
"missing public key file; expected file to exist: " + pub_filepath
)
# Generate public key from private key
with open(prv_filepath, "r") as f:
private_key_file = f.read()
private_key = serialization.load_pem_private_key(
bytes(private_key_file, "utf-8"),
password=None,
backend=default_backend(),
)
public_key = private_key.public_key()
public_key = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
public_key = public_key.decode("utf-8")
with open(pub_filepath, "w") as f:
f.write(public_key)

if not os.path.isfile(prv_filepath):
raise EnvironmentError(
"missing public key file; expected file to exist: " + prv_filepath
"missing private key file; expected file to exist: " + prv_filepath
)

with open(pub_filepath, "r") as f:
Expand Down
1 change: 1 addition & 0 deletions keys/key/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Need this folder for permission reasons inside the container
Loading

0 comments on commit 16aa5b4

Please sign in to comment.