gravitee-io / issues

Gravitee.io - API Platform - Issues
65 stars 26 forks source link

APIM - REST APIs security: Default users may exist when configuring rest apis with env variables #4161

Open prutsert opened 4 years ago

prutsert commented 4 years ago

Using environment variables (or system properties) to override the configuration in gravitee.yml, has a security impact, when leaving the 'memory' security provider enabled.

Leaving the memory provider enabled is a good practice, according to the documentation on the 'In memory' provider:

It’s a basic in-memory implementation, a simple and convenient way to declare "technical" users such as the administrator users. A good practice is to always have an admin account which can login in gravitee even if the others authentication methods are broken.

The default configuration has 4 predefined users. When I replace the first user with a custom administrator user, using environment variables, the other 3 users will still be the one configured in the default config. One of these users, user admin, will have full control over everything (roles: ORGANIZATION:ADMIN,ENVIRONMENT:ADMIN).

Expected Behavior

When configuring custom in-memory users with environment variables or system properties, no other in-memory users should exist, besides the ones configured.

Current Behavior

When configuring 1 in-memory user using environment variables, there will in fact still be 4 users, 3 of which are default users with default passwords.

Possible Solution

Comment out all but the first in-memory user in the default configuration. Generate a warning on startup, when any of the default users are active (just like the warning that is shown when the jwt secret has a default value).

Steps to Reproduce (for bugs)

  1. Leave the default configuration as is.
  2. Create one in-memory user, using environment variables: export GRAVITEE_SECURITY_PROVIDERS_0_USERS_0_USERNAME='bob' export GRAVITEE_SECURITY_PROVIDERS_0_USERS_0_PASSWORD='$2y$10$IHt//0ASqt0.QJKh7pVeeeC9Ar7ka3unB0AnRAVUv327eP3Sf9UGe'
  3. Start gravitee REST APIs in the same command line session.
  4. Open your browser and point it to an API that requires authentication, for example the policies API: http://localhost:8083/management/organizations/DEFAULT/environments/DEFAULT/policies The browser will prompt for a username and password.
  5. Use the second user that is configured in gravitee.yml:
    • Username: admin
    • Password: admin
  6. Enjoy the fact that you can view the list of policies. Now open the management user interface and start breaking things.

Context

I'm deploying gravitee APIM 3.1 on Kubernetes, by deploying each docker image as a separate deployment (no Helm chart). I'm using environment variables to configure everything, not touching the Docker images that gravitee.io provides (leaving the default configuration in place).

YoranSys commented 4 years ago

Hi, As a workaround, you can modify your deployment and add a configMap with your custom gravitee.yml with your user in memory without a password and a secret mapping as environment variable for the password.

prutsert commented 4 years ago

Hi Yoran, Using a configMap would be a great workaround, I hadn't thought of that, thanks. What I did in the mean time, was create enough users to override all the defaults. The users that I don't really need just got an invalid password (not a brypt hash).

prutsert commented 4 years ago

It actually appears to be worse than I first though, my workaround doesn't work.

When I deploy the Gravitee REST APIs with the following environment, the first username (my_admin_account) and password actually work. The second username (my_user_account), which has exactly the same password in the configuration I use, can only log in with the built in password admin, not with the password that I put in the environment. The user does get the roles that I put in the environment.

(...)
    spec:
      containers:
      - name: graviteeio-management-api
        image: graviteeio/apim-management-api:3.1
        ports:
        - containerPort: 8083
        env:
        - name: gravitee_security_providers_0_type
          value: "memory"
        - name: gravitee_security_providers_0_users_0_username
          value: "my_admin_account"
        - name: gravitee_security_providers_0_users_0_password
          value: "$2a$12$(an encrypted password)"
        - name: gravitee_security_providers_0_users_0_roles
          value: "ORGANIZATION:ADMIN,ENVIRONMENT:ADMIN"
        - name: gravitee_security_providers_0_users_1_username
          value: "my_user_account"
        - name: gravitee_security_providers_0_users_1_password
          value: "$2a$12$(an encrypted password)"
        - name: gravitee_security_providers_0_users_1_roles
          value: "ORGANIZATION:USER,ENVIRONMENT:USER"
(...)

So, putting the username and the roles in the environment works for the first and the second user, but the password only works for the first user.

Am I making something obviously mistake here?