docker-robot-framework icon indicating copy to clipboard operation
docker-robot-framework copied to clipboard

User restrictions are limiting the use of ssl certifications

Open Rabieezz opened this issue 4 years ago • 22 comments

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,

Rabieezz avatar Dec 10 '20 14:12 Rabieezz

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}

UltimateDogg avatar Dec 10 '20 16:12 UltimateDogg

@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.

Rabieezz avatar Dec 10 '20 16:12 Rabieezz

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

UltimateDogg avatar Dec 10 '20 18:12 UltimateDogg

@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.

Rabieezz avatar Dec 11 '20 08:12 Rabieezz

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

UltimateDogg avatar Dec 11 '20 10:12 UltimateDogg

@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.

Rabieezz avatar Dec 11 '20 13:12 Rabieezz

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.

UltimateDogg avatar Dec 11 '20 13:12 UltimateDogg

@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 ?

Rabieezz avatar Dec 11 '20 14:12 Rabieezz

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

UltimateDogg avatar Dec 11 '20 14:12 UltimateDogg

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

ppodgorsek avatar Dec 11 '20 15:12 ppodgorsek

@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 avatar Dec 11 '20 15:12 Rabieezz

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 ?

Rabieezz avatar Dec 17 '20 13:12 Rabieezz

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.

UltimateDogg avatar Dec 17 '20 14:12 UltimateDogg

@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.

ppodgorsek avatar Dec 18 '20 19:12 ppodgorsek

Hi @ppodgorsek @UltimateDogg ,

Let's summarize our need:

  • we're using your Docker image in a CI/CD context (GitLab CI more precisely but I guess the problem shall be the same with other CI/CD tools using Docker images)
  • in some cases we may have to request a server with a SSL certificate issued by a custom CA certificate
  • in that case - prior to running Robot Framework tests - we wish to add our custom CA certificate(s) into the container (we usually append them to /etc/ssl/certs/ca-certificates.crt)
  • unfortunately the default user of your Docker image doesn't have the required permission and GitLab CI doesn't provide any way of changing the user / UID when running the Docker image

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:

  • use root as the default docker user (I'm not fond of this solution but that's actually what most tools do; for instance Cypress, Postman/Newman, Puppeteer, ...)
  • provide some other way to enable the default user to append custom CA certificates in /etc/ssl/certs/ca-certificates.crt

pismy avatar Dec 21 '20 15:12 pismy

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.

ppodgorsek avatar Dec 21 '20 15:12 ppodgorsek

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.

pismy avatar Dec 22 '20 08:12 pismy

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.

ppodgorsek avatar Jan 01 '21 13:01 ppodgorsek

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

pismy avatar Jan 07 '21 08:01 pismy

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

UltimateDogg avatar Jan 07 '21 13:01 UltimateDogg

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

pismy avatar Jan 08 '21 05:01 pismy

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.

ppodgorsek avatar Jan 12 '21 13:01 ppodgorsek