ppodgorsek / docker-robot-framework

Robot Framework in Docker
https://cloud.docker.com/repository/docker/ppodgorsek/robot-framework
MIT License
344 stars 239 forks source link

User restrictions are limiting the use of ssl certifications #314

Open Rabieezz opened 3 years ago

Rabieezz commented 3 years ago

Hello Paul, To create an open source template for robot framework I chosed to use your docker image since it is very well maintained, my issue is that the UID and GID of the default user are blocking the possibility of redefining/creating the ssl certifications which leads the RF test to fail before starting.

So I was wondering if you consider enhancing the image by redfining the default USER UID and GID in the manifest to enlarge its scope of actions ?

Additional context My request is driven by the fact that your image is well maintained which makes a good point for the longevity of use.

Error text

$ install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
/bin/sh: eval: line 143: can't create /etc/ssl/certs/ca-certificates.crt: Permission denied
/bin/sh: eval: line 147: can't create /etc/ssl/cert.pem: Permission denied

Regards,

UltimateDogg commented 3 years ago

at run time you can define the user for your needs using the flags docker provides aka --user=1001:1001 if you are extending the base image add USER root do your commands and then put in the dockerfile

USER ${ROBOT_UID}:${ROBOT_GID}

Rabieezz commented 3 years ago

@UltimateDogg

Thank you for answer, but the goal is not to define the user manually at each run since the template will be used through Gitlab and automated that's why a user with more power to create the certificates will be ideal as a solution.

UltimateDogg commented 3 years ago

ok so you want to install certificates at run time or in an extended dockerfile at build time?

Rabieezz commented 3 years ago

@UltimateDogg the certificate part in the script is executed right after runing the container based on the image.

If you need more explanations please let me know.

UltimateDogg commented 3 years ago

To run at runtime, you should be able to run docker as user root. You can also maybe try one of the things here: https://medium.com/@paraspatidar/add-self-signed-or-ca-root-certificate-in-kubernetes-pod-ca-root-certificate-store-cb7863cb3f87

Rabieezz commented 3 years ago

@UltimateDogg Thank you but I think I may not have given you the full picture or that my explanation is not that clear.

We created a a robot framework template that use your image and it is launched through gitlab in the aime of having a fully opensourced template.

in the template I use RF lint we also need some actions to be performed by the default user and since I am using your image the default user does not have the rights to do some actions like creating SSL certificats in /etc/ssl/certs/ca-certificates.crt.

so my inquiry is mainly to know if it is possible to grant the default user on your image (by you) more rights in order to make it easy when a template is fully automated ( launched by gitlab), that's all I want to know?

as I said the goal is to use the image as is without rebuilding it( because the image need to be maintained), or changing the entrypoint which is not a best practice when you use Gitlab.

UltimateDogg commented 3 years ago

I dont think it is possible the way its setup to have the user inside the container be able to do items that would require sudo with out adding it sudoers or running the docker as root. #147 is tracked as an enhancement and would probably help the specific example you mention but no i dont think there is a generic solution right now.

Rabieezz commented 3 years ago

@UltimateDogg

S if I understand the default user will have this awkward UID and GID and will never be part of the sudoers in your image ?

UltimateDogg commented 3 years ago

Correct, but like i said above you can always change the user /group that it runs as. Here is a tutorial on it https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf and here is an example directly in our readme https://github.com/ppodgorsek/docker-robot-framework#security-consideration

ppodgorsek commented 3 years ago

I have a silly question: I don't understand why don't you run the image with --user=root, like @UltimateDogg suggested initially?

docker run --user=root ppodgorsek/robot-framework:latest

If that doesn't work, try using root's UID and GID:

docker run --user=0:0 ppodgorsek/robot-framework:latest
Rabieezz commented 3 years ago

@ppodgorsek @UltimateDogg

Thank you for your answers maybe I haven't explained the context the run is done through gitlab CI/CD pipline that calls your image in this case we don't have the ability, as in docker mode, to specify a diffrent user so the goal is to give enough rights to the default user to be able to create the ssl files accordignly.

if the possibility to change the default user in your image is not possible,could you give enough rights to this user at least for the /etc/ssl/ folders.

My second request is that I saw that the linter is missing in your image and it would be nice to add it in order to meet the critera of CI/CD context.

Rabieezz commented 3 years ago

Hello @UltimateDogg and @ppodgorsek

I applied some changes to your Dockerfile in order to overcome the problem I faced with the original image.

I added these three lines :

The lint version variable

ENV LINT_VERSION 1.1

In order to use the rflint on my test robots

robotframework-lint==$LINT_VERSION \ 

And the needed rights for the user to create the ssl certificates:

#Allow any user to create ssl certificates
RUN chmod -R ugo+w /etc/ssl \
  && chown -R ${ROBOT_UID}:${ROBOT_GID} /etc/ssl

Do you think you could apply these changes and re-push your image so it will be suitable for Gitlab CI/CD users ?

UltimateDogg commented 3 years ago

That is a pretty specific fix, i think if we decide to support we would just allow sudo access.

@ppodgorsek right now we just support using uids, but dont actually make any users. I could change it to add a user like so:

RUN addgroup \
    -gid GID  "$ROBOT_GID" 
    "robot" \
    && adduser \
    --disabled-password \
    --home "/opt/robotframework" \
    --ingroup "robot" \
    --no-create-home \
    --uid "$ROBOT_UID" \
    "robot"

And then

RUN echo "robot ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/robot && \
    chmod 0440 /etc/sudoers.d/robot

I don't know the security implications of this or what would happen if someone choose to run as a different user. Id also have to see exactly what tweaking is needed for alpine to run the above commands.

ppodgorsek commented 3 years ago

@Rabieezz Unfortunately, the line you suggested below is only run upon the image creation, not dynamically at runtime:

#Allow any user to create ssl certificates
RUN chmod -R ugo+w /etc/ssl \
  && chown -R ${ROBOT_UID}:${ROBOT_GID} /etc/ssl

This means it would break if anyone uses a different UID or GID on runtime.

@UltimateDogg This can already be done with the native Docker user remapping, I don't think we should do specific changes on our side to support it.

pismy commented 3 years ago

Hi @ppodgorsek @UltimateDogg ,

Let's summarize our need:

We could specialize your image to workaround this issue (and actually that's what we currently do), but them we're compelled to keep an eye on any new version ad release a new forked image to stay up-to-date with your image.

That would be so much more convenient to either:

ppodgorsek commented 3 years ago

Hi @pismy , Thank you for the recap, I understand why you would like to avoid having to maintain an image if it can be done here ;)

Regarding the use of root as the default user, we moved away from that a few months ago. I would feel reverting the change would be a regression, especially when not being able to set the user is in reality a GitLab problem.

I anyway did some research and it seems the Docker user remapping feature is supported by GitLab, see the GitLab Advanced Configuration. In your [runners.docker] section, rely on the userns_mode option. You would have to add something like:

[runners.docker]
  userns_mode = "root"

From what I understand, the syntax should be the same as the official Docker one, more details can be found in the Docker Documentation: Isolate containers with a user namespace. In the above example, this means the default user 1000 within the container would actually be user root from the host.

It is possible that GitLab forbids the use of root, in which case you could do a similar remapping with the user who owns your TLS certificate files. It should take either the user/group name or UID/GID.

If the remapping syntax for GitLab is different from Docker's official one, I would suggest you get in touch with the GitLab support team.

Let me know if this helps please.

pismy commented 3 years ago

Right,

Unfortunately GitLab Advanced Configuration is reserved to admin, and defining this setting would have an impact on all used Docker images (which is not what we want: unpredictable impacts). I guess we'll have to stick to the forked image way.

Just remind that our need is not necessarily using root as the default user, but more a way of adding a custom CA certificate when testing an https server with a certificate issued by a non defaut CA.

For you knowledge we have the same issue with the official SonarScanner Docker image (impossible to add custom CA certificates), compelling us to maintain our own forked Docker image. A few months ago they provided an official way of doing so.

All those DevSecOps tools are very much used in CI/CD context, and many companies have their own internal Certificate Authority.

Thanks anyway.

ppodgorsek commented 3 years ago

I created a new branch (issue-147) to enable a default feature of Firefox for the import of Enterprise CA certificates. It is still a work in progress but would this solve your issue?

I must still enable a similar feature for Chrome too.

pismy commented 3 years ago

Hi @ppodgorsek, Well I guess that would solve the issue at least partially.

Are all RobotFramework tests executed in a browser ?

I'm thinking about API tests using RequestsLibrary for instance ?

Example:

*** Settings ***
Library               Collections
Library               RequestsLibrary

*** Test Cases ***
Order Burger
    Create Session    backend            ${BASE_URL}
    ${resp}=          Delete request    backend     /api/burger/top
    Request Should Be Successful        ${resp}
    Dictionary Should Contain Key       ${resp.json()}                               id
    Should Be Equal                     ${resp.json()['name']}                       burger
    Dictionary Should Contain Key       ${resp.json()}                               ingredients
    Length Should Be                    ${resp.json()['ingredients']}                9
    Should Be Equal                     ${resp.json()['ingredients'][0]['name']}     bun
    Should Be Equal                     ${resp.json()['ingredients'][1]['name']}     ketchup
    Should Be Equal                     ${resp.json()['ingredients'][2]['name']}     mayo
    Should Be Equal                     ${resp.json()['ingredients'][3]['name']}     tomato
    Should Be Equal                     ${resp.json()['ingredients'][4]['name']}     salad
    Should Be Equal                     ${resp.json()['ingredients'][5]['name']}     bacon
    Should Be Equal                     ${resp.json()['ingredients'][6]['name']}     cheddar
    Should Be Equal                     ${resp.json()['ingredients'][7]['name']}     steak
    Should Be Equal                     ${resp.json()['ingredients'][8]['name']}     cheddar

List Purchases
    Create Session    backend            ${BASE_URL}
    ${resp}=          Get request       backend     /api/burger/purchases
    Request Should Be Successful        ${resp}
    Dictionary Should Contain Key       ${resp.json()}     elements
UltimateDogg commented 3 years ago

No Requests and anything but the selenium library would not be effected by that.

pismy commented 3 years ago

Right, that's what I was afraid of. Too bad.

ppodgorsek commented 3 years ago

By default, the Python SSL module uses the system CA certificate bundle, there should therefore be no issue at all when not relying on browsers. They are the real headache here.