Skip to content

Add support for file-based environment variables #19856

Closed
@aminosbh

Description

@aminosbh

Feature Description

In the new container-centric kubernetes-oriented world, storing secrets (or other related data) inside the ini settings file as plain text could be a major security threat and could lead to secrets end up being pushed to a git repository. And managing secrets as plain text in environment variables could also represent a security threat in setups that are using monitoring/reporting/orchestrating tools that log and store environment variables. That's why docker/Kubernetes and other tools offer the ability to manage secrets as separate artifacts in a secure way (on-disk encrypted, plain-text inside the container).

When using docker secret or other tools like Kubernetes, HashiCorp Vault, ... and were the secret is mounted as a file in /run/secrets/<SECRET_NAME> there is a need for a mechanism to load those secrets from the mounted-plain-text-files to make them available to gitea.

The proposal is that any settings in app.ini can be set or overridden with the content of a file by defining an environment variable of the form: GITEA__section_name__KEY_NAME__FILE that points to a file (in case of docker secrets it could point to /run/secrets/<SECRET_NAME>).

This technique could be used in docker-compose.yml as follows:

version: '3.9'
services:
  server:
    container_name: gitea
    image: gitea/gitea:1.16.8
    environment:
      USER_UID: 1000
      USER_GID: 1000
      # Database
      GITEA__database__DB_TYPE: postgres
      GITEA__database__HOST: gitea-db:5432
      GITEA__database__NAME: gitea
      GITEA__database__USER: gitea
      GITEA__database__PASSWD__FILE: /run/secrets/gitea_db_password
    secrets:
    - gitea_db_password
    networks:
    - gitea-net
    
  db:
    container_name: gitea-db
    image: postgres:14-alpine
    environment:
      POSTGRES_DB: gitea
      POSTGRES_USER: gitea
      POSTGRES_PASSWORD_FILE: /run/secrets/gitea_db_password
    secrets:
      - gitea_db_password
    networks:
      - gitea-net

secrets:
  gitea_db_password:
    external: true

As discussed with @zeripath in #19858 I will summarize the usability and security implications of the discussed implementations:
🟢 for positive point, 🔴 for negative point and empty when N/A or could be prevented

  1. Save secrets in ini file (Current implementation)
  2. Save secrets in overlaid dedicated ini file
  3. Make every key have an optional __FILE ending which would automatically read from a file.
    a. Implemented inside gitea: Load secrets from files to memory.
    b. Implemented inside environment-to-ini: Load secrets from file and populate ini file inside the container. Add support for file-based environment variables in environment-to-ini #19857
  4. Make a dedicated secrets section in init file and load from files to memory.
Implication 1 (Current) 2 3.a 3.b #19857 4
Secrets as plain text in the host 🔴
Secrets encrypted in the host (docker secret, Kubernetes, HashiCorp Vault, ...) 🟠 🟢 🟢 🟢
Secrets grouped with the other settings 🔴
Secrets separated from the other settings[*] 🟢 🟢 🟢 🟢
Secrets as plain text inside the container[**] 🔴 🔴 🔴 🔴 🔴
Secrets as plain text in volumes[***] 🟡 🟡
Secrets re-usable with other containers (wide usage) 🟢 🟢 🟢
Major update to ini file 🔴
Update only environment-to-ini 🟣

🟠 : Managing the whole overlaid ini file (dedicated for secrets) with docker secret
🟣 : I don't know if it could be a positive or negative point (in the short run) but the risk of breaking gitea is reduced and, for sure, for the long run it is better to implement it gitea-side.
[*]: When the secrets are separated from the general settings they could be managed by docker secret and mounted only when running the container.
[**]: In all cases the secrets mounted as files will be present as plain text inside the container.
[***]: Having secrets as plain text in volumes could be a security risk but could be mitigated if using an encrypted filesystem and setting the correct file-permission for the volume directory to prevent unprivileged processes from accessing it.

Screenshots

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/featureCompletely new functionality. Can only be merged if feature freeze is not active.type/proposalThe new feature has not been accepted yet but needs to be discussed first.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions