images icon indicating copy to clipboard operation
images copied to clipboard

Rust: Permissions Question

Open CodeMan99 opened this issue 2 years ago • 10 comments

Scenario

The rust image currently has umask 022 set.

$ docker run -it --rm --user root mcr.microsoft.com/devcontainers/rust:1-1-bullseye
root ➜ / $ umask
0022
root ➜ / $ grep ^rustlang /etc/group
rustlang:x:999:vscode

Should a build step, such as a feature use cargo install the resulting permissions prevent group write usage.

root ➜ / $ cargo install --quiet bacon
root ➜ / $ ls -ld $CARGO_HOME/registry
drwxr-sr-x 5 root rustlang 4096 Nov 14 19:04 /usr/local/cargo/registry

Which then in turn breaks user-level usage of other cargo commands.

root ➜ / $ su vscode
vscode ➜ / $ cd
vscode ➜ ~ $ cargo install cargo-watch
    Updating crates.io index
  Downloaded cargo-watch v8.4.1
error: failed to download replaced source registry `crates-io`

Caused by:
  failed to open `/usr/local/cargo/registry/cache/index.crates.io-6f17d22bba15001f/cargo-watch-8.4.1.crate`

Caused by:
  Permission denied (os error 13)

Question

What is the correct course of action?

  1. Set umask 002 here, at the image level? Perhaps in /etc/profile?
  2. Set umask 002 inside feature install.sh scripts?

CodeMan99 avatar Nov 14 '23 19:11 CodeMan99

Hi 👋

Thanks for opening a detailed issue.

What is the correct course of action?

As cargo is installed by the Rust Feature, it makes sense to update permissions in the Feature. However, looking at https://github.com/devcontainers/features/blob/main/src/rust/install.sh#L156, I do see umask 0002 set. However, I think there's a bug in this line https://github.com/devcontainers/features/blob/main/src/rust/install.sh#L163, it updates permissions only for the specific directory, instead of doing that recursively.

I believe, updating chmod g+r+w+s "${RUSTUP_HOME}" "${CARGO_HOME}" to 👇 should help.

chmod -R g+r+w+s "${RUSTUP_HOME}" "${CARGO_HOME}"

@CodeMan99 Let me know if that makes sense to you, thanks!

samruddhikhandale avatar Nov 14 '23 22:11 samruddhikhandale

Opened https://github.com/devcontainers/features/pull/754

samruddhikhandale avatar Nov 14 '23 22:11 samruddhikhandale

Let me know if that makes sense to you, thanks!

I am not completely sure to be honest. I don't think the feature creates $CARGO_HOME/regitstry. I believe that folder is only created after usage of cargo install.

So the rust feature still isn't responsible for the creation of the problem directory.

CodeMan99 avatar Nov 14 '23 22:11 CodeMan99

I think I missed the part where you switch the users between running cargo install command. As the registry is created by the root user, it won't automatically allow the vscode user to use it unless the permissions are updated.

Curious, @CodeMan99 why do you switch users? I believe these Features/images were created hoping that the same user is been used for lifecycle of the dev container. Else, it would cause permission issues as seen in this issue ^

samruddhikhandale avatar Nov 15 '23 00:11 samruddhikhandale

Curious, @CodeMan99 why do you switch users? I believe these Features/images were created hoping that the same user is been used for lifecycle of the dev container. Else, it would cause permission issues as seen in this issue ^

Usage of root is build-like usage. For example, using cargo install inside a feature install.sh. My understanding that executing that script will always be root. Is that an incorrect assumption?

Then, during development cargo will need write access to that folder. Including cargo build. The $CARGO_HOME/registry folder is created with the correct group (rustlang) in my example.

CodeMan99 avatar Nov 15 '23 02:11 CodeMan99

My understanding that executing that script will always be root. Is that an incorrect assumption?

Yes, that is correct. All Feature's install scripts are run with the root user.

With the Rust Feature, CARGO_HOME directory is correctly owned by the vscode user. However, as you are running cargo commands with the root user, it creates the registry folder with root permissions. The non-root user cannot modify the files that were created by root as basically you can't mix something like sudo cargo install and cargo install.

Hence, I believe you should do either of the following to fix the issue -

  • Always stick with a single user vscode or root, else, you will run into this issue
    • Else, manually give permissions for the registry directory to the vscode user
  • When running with root, make sure to run commands as vscode user (eg. vscode -c "cargo install bacon")

samruddhikhandale avatar Nov 17 '23 01:11 samruddhikhandale

However, as you are running cargo commands with the root user, it creates the registry folder with root permissions.

The folder is created with exactly these permissions.

root ➜ / $ cargo install --quiet bacon
root ➜ / $ ls -ld $CARGO_HOME/registry
drwxr-sr-x 5 root rustlang 4096 Nov 14 19:04 /usr/local/cargo/registry

The vscode user is added to the rustlang group by the rust feature. The only thing that needs to change is the write permissions for the group.

  • Always stick with a single user vscode or root, else, you will run into this issue

This advice does not resolve the issue. Example devcontainer.json file:

{
     "image": "mcr.microsoft.com/devcontainers/rust:1-1-bullseye",
     "features": {
         "ghcr.io/lee-orr/rusty-dev-containers/bacon:0": {}
     }
}

This very simple configuration creates the problem:

  1. cargo install bacon is run in the install.sh of the feature.
  2. The remoteUser is vscode.

So again, what is the correct course of action?

Use of umask 002 in the image's /etc/profile file? Or use of umask 002 in the install.sh script of any given feature?

CodeMan99 avatar Nov 17 '23 03:11 CodeMan99

Let me clarify a little - "the course of action" is a question of who needs to own this knowledge.

  1. Setting the umask 002 in /etc/profile would be an image-wide change, affecting all system user's default. Only image maintainers would be required to have knowledge.
  2. Setting the umask 002 in any given feature is a very specific change that requires documentation. Both documentation maintainers and community feature maintainers are required to have knowledge.
  3. Just providing a guideline puts the ownership of this issue in the hands of any user that wants to use cargo install as a build step (Dockerfile or using a feature).

CodeMan99 avatar Nov 20 '23 18:11 CodeMan99

A configuração de umask influencia as permissões padrão atribuídas a novos arquivos e diretórios criados pelos processos no sistema. O valor padrão, umask 022, significa que as permissões padrão são 755 para diretórios e 644 para arquivos. Se você deseja alterar o valor padrão do umask, pode fazer isso no arquivo de perfil (como .bashrc ou .bash_profile) do usuário ou no script de inicialização do contêiner.

Aqui está um exemplo de como você poderia configurar o umask em um arquivo de perfil (por exemplo, .bashrc) no Dockerfile:

FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye

Configurando o umask no perfil do usuário

RUN echo "umask 022" >> /etc/skel/.bashrc

Configurando o umask para o usuário existente 'vscode'

RUN echo "umask 022" >> /home/vscode/.bashrc

Dockerfile

Copy code FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye

Configurando o umask no perfil do usuário

RUN echo "umask 022" >> /etc/skel/.bashrc

Configurando o umask para o usuário existente 'vscode'

RUN echo "umask 022" >> /home/vscode/.bashrc Este Dockerfile adiciona a linha umask 022 ao final do arquivo .bashrc no diretório /etc/skel (um esqueleto usado para criar novos usuários) e ao arquivo .bashrc do usuário existente 'vscode'. Isso garantirá que o umask seja configurado corretamente para qualquer novo usuário que seja criado e para o usuário existente.

Lembre-se de que esta é uma sugestão geral, e a configuração específica pode depender dos requisitos e das práticas recomendadas em sua organização. Certifique-se de ajustar conforme necessário para atender às suas necessidades específicas.

Parece que o problema está relacionado às permissões do diretório /usr/local/cargo/registry. Você pode otimizar isso ajustando as permissões para garantir que o usuário vscode tenha as permissões apropriadas para acessar e gravar nesse diretório. Uma abordagem possível seria adicionar o usuário vscode ao grupo rustlang e ajustar as permissões do diretório.

Aqui estão as etapas que você pode adicionar ao seu Dockerfile:

FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye

# Adiciona o usuário 'vscode' ao grupo 'rustlang'
RUN usermod -aG rustlang vscode

# Define as permissões do diretório '/usr/local/cargo/registry'
RUN chown root:rustlang /usr/local/cargo/registry && chmod 775 /usr/local/cargo/registry

# Configura o umask no perfil do usuário
RUN echo "umask 022" >> /etc/skel/.bashrc
RUN echo "umask 022" >> /home/vscode/.bashrc

FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye

# Adiciona o usuário 'vscode' ao grupo 'rustlang'
RUN usermod -aG rustlang vscode

# Define as permissões do diretório '/usr/local/cargo/registry'
RUN chown root:rustlang /usr/local/cargo/registry && chmod 775 /usr/local/cargo/registry

# Configura o umask no perfil do usuário
RUN echo "umask 022" >> /etc/skel/.bashrc
RUN echo "umask 022" >> /home/vscode/.bashrc

Estas são as principais alterações:

  1. usermod -aG rustlang vscode: Adiciona o usuário vscode ao grupo rustlang.
  2. chown root:rustlang /usr/local/cargo/registry: Define o proprietário do diretório /usr/local/cargo/registry como root e o grupo como rustlang.
  3. chmod 775 /usr/local/cargo/registry: Define as permissões do diretório como 775, permitindo que o grupo rustlang também escreva no diretório.

Depois de adicionar essas linhas ao seu Dockerfile e reconstruir a imagem, o usuário vscode deve ter as permissões adequadas para instalar pacotes Cargo sem erros de permissão. Certifique-se de que essas alterações atendam aos requisitos específicos do seu ambiente.

Peço desculpas pela confusão anterior. Parece que mesmo após adicionar o usuário vscode ao grupo rustlang e ajustar as permissões do diretório, ainda ocorrem problemas de permissão.

A solução proposta anteriormente para alterar as permissões do diretório pode não ser suficiente. É possível que as permissões específicas do arquivo index.crates.io-6f17d22bba15001f/cargo-watch-8.4.1.crate não estejam permitindo que o usuário vscode acesse.

Uma solução mais robusta pode ser garantir que todos os arquivos e diretórios dentro de /usr/local/cargo/registry tenham as permissões adequadas para o grupo rustlang. Você pode fazer isso recursivamente usando o comando chmod:


FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye

# Adiciona o usuário 'vscode' ao grupo 'rustlang'
RUN usermod -aG rustlang vscode

# Define as permissões do diretório '/usr/local/cargo/registry'
RUN chown -R root:rustlang /usr/local/cargo/registry && chmod -R 775 /usr/local/cargo/registry

# Configura o umask no perfil do usuário
RUN echo "umask 022" >> /etc/skel/.bashrc
RUN echo "umask 022" >> /home/vscode/.bashrc

FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye

# Adiciona o usuário 'vscode' ao grupo 'rustlang'
RUN usermod -aG rustlang vscode

# Define as permissões do diretório '/usr/local/cargo/registry'
RUN chown -R root:rustlang /usr/local/cargo/registry && chmod -R 775 /usr/local/cargo/registry

# Configura o umask no perfil do usuário
RUN echo "umask 022" >> /etc/skel/.bashrc
RUN echo "umask 022" >> /home/vscode/.bashrc

Nesta versão, a alteração chmod -R 775 /usr/local/cargo/registry é usada para aplicar as permissões recursivamente a todos os arquivos e subdiretórios dentro de /usr/local/cargo/registry. Isso deve garantir que o usuário vscode tenha acesso suficiente para instalar pacotes Cargo sem problemas de permissão.

Após fazer essas alterações e reconstruir a imagem, tente novamente instalar o cargo-watch como o usuário vscode. Isso deve resolver os problemas de permissão.

GKMWD avatar Nov 29 '23 17:11 GKMWD

Opened devcontainers/features#754

This PR is what I want. Now I have an error using the cargo build command due to permission being denied. Perhaps it's because I used cargo to install some tools in the dockerfile before run rust feature script, so the gid in the registry directory is root

non-root@702362714ab7:~$ ls -l $CARGO_HOME
total 24
drwxrwxrwx 1 root root     4096 May 22 08:04 bin
-rwxr-xr-x 1 root rustlang  690 May 21 16:06 config.toml
-rw-rw-rw- 1 root root      308 May 14 03:57 env
drwxrwxr-x 1 root root     4096 May 22 08:04 registry

non-root@702362714ab7:~$ ls -l $RUSTUP_HOME
total 20
drwxrwxrwx 1 root root 4096 May 22 09:04 downloads
-rw-rw-rw- 1 root root  151 May 14 03:58 settings.toml
drwxrwxrwx 1 root root 4096 May 22 09:04 tmp
drwxrwxrwx 1 root root 4096 May 22 09:04 toolchains
drwxrwxrwx 1 root root 4096 May 22 09:04 update-hashes

Can this PR be merged?

gamife avatar May 22 '24 09:05 gamife