Azure / azure-functions-docker

This repo contains the base Docker images for working with azure functions
MIT License
262 stars 117 forks source link

Support running as non-root, on a high port #424

Open paulgear opened 3 years ago

paulgear commented 3 years ago

Hi everyone,

We use mcr.microsoft.com/azure-functions/dotnet:3.0 to implement function apps via KEDA, and we want to run all of our containers with Azure's "Kubernetes cluster pod security restricted standards for Linux-based workloads" policy. This means we need both to run as non-root, and to disallow privilege escalation via setcap. Could you please consider adding this capability?

Thanks, Paul

Barre14 commented 3 years ago

We need this too. We would like to enforce some of the policies from Azure Policy, which requires our pods to run with runAsNonRoot = true. Could you please fix this, so we can run the images in the most secure way?

thx,

Bart

EdmondAndy commented 2 years ago

we are using mcr.microsoft.com/azure-functions/dotnet:3.0 for running azure function apps inside AKS, when run as non-root, and to disallow privilege escalation are not working, workload just silently failed and not logging any errors. want to confirm if this is supported now? if not, can you please also explain the reason why it is not supported as run as non root user since this is a big security concern

mtaron commented 2 years ago

I just hit this and it still doesn't appear to be supported. I see this in the logs:

Durable task hub worker started successfully after 28ms ... [ so far so good] Host started (851ms) ... [ nice ] Job host started ... [ but then everything falls apart ] Stopped the listener 'Microsoft.Azure.WebJobs.Extensions.Http.HttpTriggerAttributeBindingProvider+HttpTriggerBinding+NullListener' for function 'MyFunctionName' ... [ repeated for every endpoint, and finally ] Stopping task hub worker. IsGracefulStop: False. InstanceId: . Function: . HubName: MyHub. AppName: . SlotName: . ExtensionVersion: 2.5.1. SequenceNumber: 2. Durable task hub worker is stopping (isForced = True) ... Application is shutting down...

You'd think after the container escape that security features like running as a non-root user would be prioritized.

wsugarman commented 2 years ago

This should definitely be prioritized

wsugarman commented 2 years ago

I've had success recently running as a non-root user with the following steps in my own dockerfile that uses the mcr.microsoft.com/azure-functions/dotnet base image:

Although, I am only running durable functions and timer triggers.

mtaron commented 2 years ago

Thanks for the workaround, @wsugarman! We tried it out on my team and it worked great!

With the announcement of .NET using Chiseled Ubuntu Containers and embracing non-root containers, it would be great if Azure Functions followed suit from both a container size and security perspective.

Nemeczek commented 1 year ago

Hey, I can see that a lot of time has passed already. Is there any estimate of when this can be addressed?

bledeamarius commented 1 year ago

I've had success recently running as a non-root user with the following steps in my own dockerfile that uses the mcr.microsoft.com/azure-functions/dotnet base image:

  • Create a new user like nonuser. (i.e. RUN groupadd + RUN useradd)
  • Grant read permissions to the host folder /azure-functions-host
  • Set the environment variable ASPNETCORE_URLS to a port above 1024, like 5000. (e.g. ENV ASPNETCORE_URLS=http://+:5000)
  • Set the user USER nonroot
  • Expose this higher port EXPOSE 5000

Although, I am only running durable functions and timer triggers.

Thank you! It also worked for mcr.microsoft.com/azure-functions/python:4-python3.9 image.

EdmondAndy commented 1 year ago

Yeah, I also managed to set the non-root user for function app previously, it worked fine with the MS provided azure-function image. forgot to reply in this thread.

vicrem commented 1 year ago

@EdmondAndy, can you plz post an example of your dockerfile? I have tried steps provided by wsugerman without luck. Pid 1 always run as root.

wsugarman commented 1 year ago

Here is an example: https://github.com/wsugarman/durabletask-azurestorage-scaler/blob/bc2559c160fae5dcbbd5882db9452f88afce6aa3/tests/Keda.Scaler.WebJobs.DurableFunctions.Examples/Dockerfile

FROM mcr.microsoft.com/azure-functions/dotnet:4 AS runtime
RUN groupadd nonroot -g 2000 && \
    useradd -r -M -s /sbin/nologin -g nonroot -c nonroot nonroot -u 1000 && \
    chown -R nonroot:nonroot /azure-functions-host
ENV ASPNETCORE_URLS=http://+:8080 \
    AzureFunctionsJobHost__FileWatchingEnabled=false \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
    AzureFunctionsJobHost__Logging__FileLoggingMode=Never \
    AzureWebJobsScriptRoot=/home/site/wwwroot \
    DOTNET_EnableDiagnostics=0 \
    FUNCTIONS_WORKER_RUNTIME=dotnet
USER nonroot
EXPOSE 8080
EdmondAndy commented 1 year ago

@vicrem fyi this is an example which I wrote last year. hopefully it helps

FROM mcr.microsoft.com/azure-functions/dotnet:4
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

EXPOSE 8080
ENV ASPNETCORE_URLS=http://*:8080

COPY . /home/site/wwwroot

RUN chmod +x /home/site/wwwroot/run.sh && sed -i -e 's/\r$//' /home/site/wwwroot/run.sh

RUN useradd -ms /bin/bash -u 1000 appuser && chown -R appuser:appuser /home/site/wwwroot && \
        chown -R appuser:appuser /azure-functions-host && chown -R appuser:appuser /FuncExtensionBundles

USER appuser

ENTRYPOINT ["/home/site/wwwroot/run.sh"]

CMD [ "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost" ]
vicrem commented 1 year ago

@EdmondAndy/@wsugarman thanks both of you. The container is now running rootless.

webflow-entertainment commented 5 months ago

I have an issue with running a function in a Docker image based on Node and Go (Custom Handler). We have also enabled authentication with Microsoft as the provider. Basically, everything works until I switch the function image to non-root. I receive a Bad Request (403) and cannot swap the function. Does anyone have an idea?

FROM mcr.microsoft.com/azure-functions/node:4.33.1 

ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
    ASPNETCORE_URLS=http://+:8080 \
    NODE_OPTIONS=--max-http-header-size=32768 \
    HOME=/home \
    FUNCTIONS_WORKER_RUNTIME=node \
    DOTNET_USE_POLLING_FILE_WATCHER=true \
    HOST_VERSION=4.33.0 \
    ASPNETCORE_CONTENTROOT=/azure-functions-host

COPY functions/ /home/site/wwwroot/

RUN groupadd nonroot -g 2000 && \
    useradd -r -M -s /sbin/nologin -g nonroot nonroot -u 1000 && \
    chown -R nonroot:nonroot /azure-functions-host && \
    chown -R nonroot:nonroot /FuncExtensionBundles && \
    chown -R nonroot:nonroot /home/site/wwwroot

USER nonroot
EXPOSE 8080

CMD [ "/azure-functions-host/Microsoft.Azure.WebJobs.Script.WebHost" ]
klemen-df commented 4 months ago

So, I have this (runing azure function on k8s/aks) and it's working:

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS builder
WORKDIR /build
COPY ./ ./
RUN dotnet publish --configuration Release --output /dist/
RUN dotnet test

FROM mcr.microsoft.com/azure-functions/dotnet:4
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    ASPNETCORE_URLS=http://+:5000 \
    DOTNET_EnableDiagnostics=0
COPY --from=builder /dist/ /home/site/wwwroot
EXPOSE 5000

but when I convert it to non-root it stops working

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS builder
WORKDIR /build
COPY ./ ./
RUN dotnet publish --configuration Release --output /dist/
RUN dotnet test

FROM mcr.microsoft.com/azure-functions/dotnet:4
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    ASPNETCORE_URLS=http://+:5000 \
    DOTNET_EnableDiagnostics=0
COPY --from=builder /dist/ /home/site/wwwroot

RUN apt-get update && apt-get install -y procps
RUN groupadd nonroot -g 2000 && \
    useradd -r -M -s /sbin/nologin -g nonroot -c nonroot nonroot -u 1000
RUN chown -R nonroot:nonroot /azure-functions-host

USER nonroot
EXPOSE 5000

The service starts but there is no host.startup / warmup.extensions...only this

Hosting environment: Production
Content root path: /azure-functions-host
Now listening on:
http://[::]:5000/
Application started. Press Ctrl+C to shut down.

So, the point is that the service/container doesn't crash when doing non-root but it somehow doesn't load the app.

Any suggestions what else to try?