[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [atomic-devel] We are working on Roles Based Access Control for docker.



On 04/07/2015 10:36 AM, Pavel Odvody wrote:
> On Tue, 2015-04-07 at 06:52 -0400, Daniel J Walsh wrote:
>> On 04/07/2015 05:57 AM, Pavel Odvody wrote:
>>> On Mon, 2015-04-06 at 11:34 -0400, Daniel J Walsh wrote:
>>>> On 04/02/2015 11:50 AM, Pavel Odvody wrote:
>>>>> On Wed, 2015-04-01 at 10:34 +0200, Pavel Odvody wrote:
>>>>>> On Tue, 2015-03-31 at 17:02 -0400, Colin Walters wrote:
>>>>>>> On Tue, Mar 31, 2015, at 04:35 AM, Pavel Odvody wrote:
>>>>>>>
>>>>>>>> It's supposed to work in the following way:
>>>>>>>> - docker daemon is started with the --trusted flag, this labels the
>>>>>>>> process as SELinux type 'docker_daemon_t', daemon also labels the
>>>>>>>> created Unix socket as 'docker_socket_t'. Define a policy that allows
>>>>>>>> only docker_daemon_t to talk to docker_socket_t. This ensures that the
>>>>>>>> daemon communicates only with compatible binary; other methods of
>>>>>>>> communication with the daemon have to be disabled (TCP).
>>>>>>> But what domains can transition to docker_daemon_t ? Is e.g. unconfined_t -> docker_daemon_t a valid transition?  If so, we aren't gaining anything AFAICS.  If it's not, what domains can?
>>>>>>>
>>>>>> The docker binary is originally labeled as docker_client_t, which is
>>>>>> also capable of talking to docker_socket_t.
>>>>>>
>>>>>>> On Tue, Mar 31, 2015, at 04:35 AM, Pavel Odvody wrote:
>>>>>>>> - each request that is sent from Docker Cli to the daemon is decorated
>>>>>>>> with 2 additional HTTP headers, UID/EUID of the user.
>>>>>>> You really want instead to have docker use `getsockopt` with `SO_PEERCRED` when the socket connection is first set up.  Anything else is subject to forgery.
>>>>>>>
>>>>>> That's nice! Didn't know about that one, sounds much better than pushing
>>>>>> HTTP headers around :)
>>>>>> Btw. the headers could not be forged, due to the policy constraints put
>>>>>> on the socket, but this one should also work with docker-py and similar
>>>>>> tools talking to the socket directly out of the box.
>>>>>>
>>>>>>
>>>>> I created a fresh branch which uses `SO_PEERCRED`, the road was bumpy
>>>>> as none of the structs actually expose the file descriptor of the
>>>>> connection or the connection object itself (reflection to the rescue!).
>>>>> Example output:
>>>>>
>>>>> # docker version
>>>>> vars: {"rgid":"0","rpid":"21855","ruid":"0","version":"1.19"}
>>>>>
>>>>> # sudo -u nginx docker version 
>>>>> vars: {"rgid":"986","rpid":"21881","ruid":"990","version":"1.19"}
>>>>>
>>>>> https://github.com/shaded-enmity/docker/compare/trusteddocker
>>>>>
>>>> You should be looking to get the loginuid not the UID or gid.  We also
>>>> have SO_PEERCON
>>>>
>>>> man getpeercon() in libselinux returns the type of the remote connection
>>>> on the socket.
>>>>
>>>> But I think we want to do this in two different steps.  First look at
>>>> the communications with the docker
>>>> socket purely from a DAC perspective.  Once we have something in place
>>>> for this, we can start looking
>>>> at the SELinux/MAC issues.
>>>>
>>>>
>>>>
>>>>
>>> I've pushed an update that also grabs the `loginuid` from 
>>> /proc/${pid}/loginuid and stores it in the `rlid` variable per each
>>> request:
>>>
>>> # docker version
>>> {"rgid":"0","rlid":"0","rpid":"2260","ruid":"0","version":"1.19"}
>>>
>>> # sudo -u nginx docker version
>>> {"rgid":"986","rlid":"0","rpid":"2267","ruid":"990","version":"1.19"}
>>>
>>> (fedora)$ sudo docker version
>>> {"rgid":"0","rlid":"1000","rpid":"2415","ruid":"0","version":"1.19"}
>>>
>>> (fedora)$ docker version
>>> {"rgid":"1000","rlid":"1000","rpid":"2382","ruid":"1000","version":"1.19"} 
>>>
>>>
>>> Now figure out what to actually do with all the IDs and how to label
>>> stuff inside docker.
>>> Do you have a Docker branch for this project or is this the only
>>> prototype?
>>>
>> Matt Heon has been looking into this.  He is doing Authentication
>> patches right now, basically we want
>> docker to confirm the other end of the connection using PAM controls. 
>> We want to support User/Password,
>> Kerberos and potentially others in the future.  We want to support not
>> only talking to the unix domain socket but
>> to a network connection.
>>
> So if socket_type == TCP then the first message received should contain
> auth info otherwise the connection is dropped? How are you sending the
> credentials? I wonder how the session is tracked since HTTP is
> stateless, so either you validate first then pass around a token, or
> validate on a per-request basis (as with the headers in my original
> solution).
> How is this going to work with with other tools expecting the current
> remote API sitting at the other end of the socket (docker-py)?
>
>> The first step I would like to see is to get proper logging/auditing.  I
>> want to see a syslog/journald/audit message
>> saying dwalsh created a privileged container named foobar with the
>> following options.
>>
> Agreed. I'll update here when I push this.
>
>> After we have logging, we could look into grouping users and machines
>> and that adding relationships/access control between them.
>>
>> Finally we would get the docker daemon to start enforcing the access
>> control.
> Is it possible to set selinux labels per-thread? If so, do these survive
> Goroutines?
> I was thinking about spawning a thread with per-user specific label to
> handle each request, but since the code is rather goroutine happy, and
> goroutines spawn threads or maybe even reuse existing ones to execute
> the workload I'm little worried that if the labels are not inherited
> that the only reasonable thing is to fork + set uid per each request.
>
>
SELinux contexts would probably not work well for this.   As you stated
with threads
passing back and forth and I am not sure about the information/memory
sharing between
the threads.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]