Repository: CTFd/CTFd

Issue:
CTFd permission error by using custom Vagrant
**Environment**:

  - CTFd Version/Commit:master
  - Operating System: VERSION="16.04.6 LTS (Xenial Xerus)"  (vagrant machine)


**What happened?**
Permission denied 
**How to reproduce your issue**
Create the following Vagrantfile
```ruby
 # Defines our Vagrant environment
 #
 # -*- mode: ruby -*-
 # vi: set ft=ruby :
 
 Vagrant.configure("2") do |config|
 
   DOCKER_REBUILD = true
   DOCKER_DESTROY = false
   config.vm.define :dockermachine do |config|
   config.vm.box = "ubuntu/xenial64"
   config.vm.hostname = "dsp"
   config.vm.provision :docker
   config.vm.provision :docker_compose
 
   # Run docker compose networks
   config.vm.synced_folder ".", "/vagrant", disabled: true
   config.vm.synced_folder "./provision/", "/provision", disabled: false
   config.vm.network "forwarded_port", guest: 8000, host: 8000
   config.ssh.keep_alive = true
   config.vm.provider "virtualbox" do |vb|
       vb.gui = false
       vb.default_nic_type = nil
       vb.memory = "2048"
     end
   end
```
Install docker plugin prerequisite: 
```
vagrant plugin install vagrant-docker-compose
```
Start machine and manually set ctfd
```bash
vagrant up 
vagrant ssh
git clone https://github.com/CTFd/CTFd.git
cd CTFd
#add secret key in docker-compose
    environment:
      - SECRET_KEY=password  
docker-compose up
```
- Issue no.1: 
The first issue is about log directory permission; the user created in Dockerfile (uid=1001) is different than the current user id(1000) . 
You can solve it by changing the userid in Dockerfile and by sending docker-compose build and docker-compose up: 
```
sed -i "s/1001/$UID/g" Dockerfile
sudo chown -hR vagrant:vagrant .data
docker-compose up --build
```  
- Issue 2:  
After these steps, the application runs, but it is not possible to go over the setup phase: 
<img width="617" alt="Schermata 2019-04-20 alle 12 58 05" src="https://user-images.githubusercontent.com/18548727/56456394-f71c7a80-636b-11e9-9c82-8d8e0319fb09.png">

<img width="1008" alt="Schermata 2019-04-20 alle 12 59 00" src="https://user-images.githubusercontent.com/18548727/56456401-216e3800-636c-11e9-876e-46d05470bce2.png">


I am not able to overcome this problem. Could you give me any hint about it? 
Thanks very much


**Any associated stack traces or error logs**
Permission denied (issue no.1): 
```
ctfd_1   | IOError: [Errno 13] Permission denied: '/var/log/CTFd/logins.log'
ctfd_ctfd_1 exited with code 1
ctfd_1   | Waiting for db: to be ready
ctfd_1   | .db is ready
ctfd_1   | Traceback (most recent call last):
ctfd_1   |   File "manage.py", line 8, in <module>
ctfd_1   |     app = create_app()
ctfd_1   |   File "/opt/CTFd/CTFd/__init__.py", line 225, in create_app
ctfd_1   |     init_logs(app)
ctfd_1   |   File "/opt/CTFd/CTFd/utils/initialization/__init__.py", line 90, in init_logs
ctfd_1   |     open(log, 'a').close()
ctfd_1   | IOError: [Errno 13] Permission denied: '/var/log/CTFd/logins.log'
ctfd_1   | Waiting for db: to be ready
ctfd_1   | db is ready
ctfd_1   | Traceback (most recent call last):
ctfd_1   |   File "manage.py", line 8, in <module>
ctfd_1   |     app = create_app()
ctfd_1   |   File "/opt/CTFd/CTFd/__init__.py", line 225, in create_app
ctfd_1   |     init_logs(app)
ctfd_1   |   File "/opt/CTFd/CTFd/utils/initialization/__init__.py", line 90, in init_logs
ctfd_1   |     open(log, 'a').close()
ctfd_1   | IOError: [Errno 13] Permission denied: '/var/log/CTFd/logins.log'
ctfd_1   | Waiting for db: to be ready
ctfd_1   | db is ready
ctfd_1   | Traceback (most recent call last):
ctfd_1   |   File "manage.py", line 8, in <module>
ctfd_1   |     app = create_app()
ctfd_1   |   File "/opt/CTFd/CTFd/__init__.py", line 225, in create_app
ctfd_1   |     init_logs(app)
ctfd_1   |   File "/opt/CTFd/CTFd/utils/initialization/__init__.py", line 90, in init_logs
ctfd_1   |     open(log, 'a').close()
ctfd_1   | IOError: [Errno 13] Permission denied: '/var/log/CTFd/logins.log'
```


Discussion:
I'm not particularly familiar with Vagrant and I don't believe I contributed the Vagrantfile. If you can debug this and PR a fix it would be welcome. 

Receiving errors about 403's like that usually means either your CSRF values are incorrect meaning you should clear cookies or you have cached data in your CTFd instance that's interfering with logged in users in which case you should probably delete the `.data` folder.  
I'm getting a similar error (Permission denied: '/var/log/CTFd/logins.log') but I'm not using Vagrant. I just cloned the repo and ran docker-compose up. I even created the folder/file and gave it full 777 permissions (because that fixes everything!) but still no luck. 
I can't reproduce at 95e4060f15abcf40db9478e4b6f8d4bfcde56050. Worked fine for me on Docker for OSX. 
@kasclark try to send sed -i "s/1001/$UID/g" Dockerfile and rebuild the image. 
@ColdHeat strange, this issue even occurred on my OSX...
Are you using docker-compose or pure docker run ? 
Do you have a ctfd user belonging to docker group that run the docker-compose ? 
I use docker-compose. I do not have a ctfd user or even a docker group. 
Might be related to #720 
What's the docker version that you're running? 
Docker version 18.09.2, build 6247962   
Anyway I have just noticed the for the OSx I have only the second issue: 
the problem is not related with log permission denied (issue no.1); but only to the 403 http error when I try to create a new user. 
Have you tried to follow all setup steps in a fresh docker-compose image? 
Now I try to remove the user info in Dockerfile (it should run as root, and fallback to the previous version running in an "unsecure" way). 

I agree with the points raised in #720 that the image doesn't need to run as root. I doubt I'm going to revert these changes unless this issue reproduces for me anywhere. 
Yes, I am completely agreed (I work in security field :)) ... anyway, I would like to run CTFd 'cause it seems awesome ! 
I keep continuing to troubleshoot. 

This is working fine for me. Perhaps you need to review your docker-compose.yml file and compare it to master? 
Was this CTFd instance created fresh or was it an upgrade from git pull? If it was from a previous installation, likely you are running into issues with the difference of user permissions. 

Until I know more, my recommendation would be to delete the contents of the log folder. 
Completely fresh github clone . Just add SECRET_KEY to docker-compose.
When I run docker-compose up for the first time, those are the permissions created from the internal containers processes: 
<img width="387" alt="Schermata 2019-04-21 alle 09 36 11" src="https://user-images.githubusercontent.com/18548727/56466953-1cb38d80-6419-11e9-9d26-7fa3b10d5823.png">  

<img width="455" alt="Schermata 2019-04-21 alle 09 36 21" src="https://user-images.githubusercontent.com/18548727/56466954-1fae7e00-6419-11e9-9d23-c87010ff6ee9.png">  

Now, when I send chown -hR vagrant:vagrant .data I am able to go on, but I am blocked to the resource protected forbidden page.

Anyway, thanks very much for your support.


@ColdHeat  I am finally be able to initialize CTFd !!!
About the second issue, something strange occurred by using Google Chrome (related to cache or cookies, anyway I always use it by disabling cache) ; Firefox saves me, and I have also tried by using Chrome with private mode and it works. 
About the first issue,  If you can tell me the container that creates those directories I will try to solve in a cleaner solution. 
Actually the solution is:
- Before running docker-compose up, change the uid inside the Dockerfile in order to align it with your current user. 
- Run docker-compose up for the first time
- Let docker-compose to create all .data structure 
- Block docker-compose up when permission denied occurs
- Send chown -hR <user>:<user> .data
- Run docker-compose up again  

The issue no.1 is resolved.
Regarding the second issue, it is not an issue, but something related with cache as you suggested.

Very likely related with: 
https://github.com/docker/compose/issues/3270
I believe I might've run into your second issue before when I was implementing the Same-Site cookies setting. If I had Devtools open when I went through setup, it would fail with a 403 but it would work if I closed Devtools and it would work in Firefox as well. 

I'm now on Chrome 73.0.3683.103. 

You didn't specify your browser version in the issue template so what is your Chrome version? 
Your same version.

I confirm that during the CTFd usage with chrome some permission error occurs. No problems by using firefox / safari

Resolving patch:
diff --git a/CTFd/utils/initialization/__init__.py b/CTFd/utils/initialization/__init__.py
--- a/CTFd/utils/initialization/__init__.py
+++ b/CTFd/utils/initialization/__init__.py
@@ -35,6 +35,7 @@
 import datetime
 import logging
 import os
+import sys
 
 
 def init_template_filters(app):
@@ -85,22 +86,37 @@ def init_logs(app):
         'registrations': os.path.join(log_dir, 'registrations.log')
     }
 
-    for log in logs.values():
-        if not os.path.exists(log):
-            open(log, 'a').close()
-
-    submission_log = logging.handlers.RotatingFileHandler(logs['submissions'], maxBytes=10000)
-    login_log = logging.handlers.RotatingFileHandler(logs['logins'], maxBytes=10000)
-    registration_log = logging.handlers.RotatingFileHandler(logs['registrations'], maxBytes=10000)
+    try:
+        for log in logs.values():
+            if not os.path.exists(log):
+                open(log, 'a').close()
+
+        submission_log = logging.handlers.RotatingFileHandler(logs['submissions'], maxBytes=10000)
+        login_log = logging.handlers.RotatingFileHandler(logs['logins'], maxBytes=10000)
+        registration_log = logging.handlers.RotatingFileHandler(logs['registrations'], maxBytes=10000)
+
+        logger_submissions.addHandler(
+            submission_log
+        )
+        logger_logins.addHandler(
+            login_log
+        )
+        logger_registrations.addHandler(
+            registration_log
+        )
+    except IOError:
+        pass
+
+    stdout = logging.StreamHandler(stream=sys.stdout)
 
     logger_submissions.addHandler(
-        submission_log
+        stdout
     )
     logger_logins.addHandler(
-        login_log
+        stdout
     )
     logger_registrations.addHandler(
-        registration_log
+        stdout
     )
 
     logger_submissions.propagate = 0


Test patch: