Skip to content
This repository has been archived by the owner on Jan 27, 2023. It is now read-only.

Commit

Permalink
Adds multi-user support into engine with a simple account/user model.
Browse files Browse the repository at this point in the history
* Adds user management and detection routes: /accounts/*, /account, /user
* New option in config.yaml for the "apiext" service: "authorization_handler" key, with default value "native". Allows extension point for other models in the future.
* Accounts have one of three types: service (internal), admin, and user. Only admin account users can create other accounts/users.
* During upgrade, existing users are migrated to accounts of the same name with user records with the same credentials.
* Adds 'x-anchore-account' header support to allow admin users to make requests in the namespace of other accounts, for example to view events or image status, without requiring api route cahgnes.
* The existing config.yaml user sections are respected during first system initialization but ignored afterwards, so user management is purely via the APIs.

Signed-off-by: Zach Hill <zach@anchore.com>
  • Loading branch information
zhill committed Oct 4, 2018
1 parent 6ed4708 commit 3fef0b7
Show file tree
Hide file tree
Showing 138 changed files with 6,610 additions and 14,280 deletions.
59 changes: 53 additions & 6 deletions Dockerfile
@@ -1,12 +1,59 @@
FROM centos:7
# Build pip wheels for all dependencies
FROM ubuntu:18.04 as wheelbuilder

ARG CLI_COMMIT=master

LABEL anchore_cli_commit=$CLI_COMMIT

ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
ENV GOPATH=/go

RUN mkdir -p /go && \
apt -y update && \
apt -y install vim curl psmisc git rpm python3 python3-pip golang btrfs-tools git-core libdevmapper-dev libgpgme11-dev go-md2man libglib2.0-dev libostree-dev && \
git clone https://github.com/containers/skopeo $GOPATH/src/github.com/containers/skopeo && \
cd $GOPATH/src/github.com/containers/skopeo && \
make binary-local && \
make install

COPY . /anchore-engine

RUN pip3 install --upgrade pip
# pip3 install --upgrade setuptools wheel

#RUN pip3 install -e git+git://github.com/anchore/anchore-cli.git@$CLI_COMMIT\#egg=anchorecli

COPY . /anchore-engine
WORKDIR /anchore-engine
RUN pip3 wheel --wheel-dir=/wheels -r requirements.txt

# Do the final build
FROM ubuntu:18.04

ARG CLI_COMMIT=master
ARG ANCHORE_COMMIT

LABEL anchore_cli_commit=$CLI_COMMIT
LABEL anchore_commit=$ANCHORE_COMMIT

ENV LANG=en_US.UTF-8
ENV LC_ALL=C.UTF-8
EXPOSE 8228 8338 8087 8082

RUN yum -y update && yum -y install epel-release && yum -y install skopeo python-pip dpkg gcc python-devel openssl-devel psmisc && yum clean all -y
RUN pip install --upgrade pip && pip install --upgrade setuptools && pip install anchorecli
RUN mkdir -p /go && \
apt -y update && \
apt -y install vim curl psmisc git rpm python3 python3-pip golang btrfs-tools git-core libdevmapper-dev libgpgme11-dev go-md2man libglib2.0-dev libostree-dev
RUN pip3 install -e git+git://github.com/anchore/anchore-cli.git@$CLI_COMMIT\#egg=anchorecli

COPY --from=wheelbuilder /wheels /wheels
COPY . /anchore-engine
COPY --from=wheelbuilder /usr/bin/skopeo /usr/bin/skopeo
COPY --from=wheelbuilder /etc/containers/policy.json /etc/containers/policy.json

WORKDIR /anchore-engine
RUN pip3 install --no-index --find-links=/wheels -r requirements.txt && pip3 install .

COPY . /root/anchore-engine
RUN cd /root/anchore-engine/ && pip install --upgrade .
ENTRYPOINT ["/usr/local/bin/anchore-manager"]
CMD ["service", "start"]

CMD /usr/bin/anchore-engine
42 changes: 0 additions & 42 deletions Dockerfile.py3

This file was deleted.

47 changes: 47 additions & 0 deletions anchore_engine/apis/__init__.py
@@ -0,0 +1,47 @@
"""
Code for common API handling that is used for all services and apis in the system
"""
import copy
import hashlib
import json

from anchore_engine.apis.context import ApiRequestContextProxy
from anchore_engine.subsys import logger


def do_request_prep(request, default_params=None):
if default_params is None:
default_params = {}

ret = {}
try:
ret['userId'] = ApiRequestContextProxy.namespace()
ret['auth'] = None, None

ret['method'] = request.method
ret['bodycontent'] = str(request.get_data(), 'utf-8') if request.get_data() is not None else None
ret['params'] = default_params
for param in list(request.args.keys()):
if type(request.args[param]) in [str, str]:
if request.args[param].lower() == 'true':
val = True
elif request.args[param].lower() == 'false':
val = False
else:
val = request.args[param]
else:
val = request.args[param]

ret['params'][param] = val

query_signature = copy.deepcopy(ret)
query_signature['path'] = request.path
query_signature.get('params', {}).pop('page', None)
query_signature.get('params', {}).pop('limit', None)
ret['pagination_query_digest'] = hashlib.sha256(json.dumps(query_signature, sort_keys=True).encode('utf8')).hexdigest()

except Exception as err:
logger.error("error processing request parameters - exception: " + str(err))
raise err

return(ret)
36 changes: 0 additions & 36 deletions anchore_engine/apis/auth/basic.py

This file was deleted.

61 changes: 61 additions & 0 deletions anchore_engine/apis/authentication.py
@@ -0,0 +1,61 @@
"""
API authentication functions and handlers for use in API processing
This is the interface exposed to services for identity.
"""
from collections import namedtuple

from anchore_engine.subsys.identities import manager_factory
from anchore_engine.subsys import logger


IdentityContext = namedtuple('IdentityContext', ['username', 'user_account', 'user_account_type', 'user_account_active'])
Credential = namedtuple('Credential', ['type', 'value'])


class IdentityProvider(object):
"""
Simple interface for read-only access to identities for use by api processing, e.g. not serving the actual user api.
"""

def __init__(self, session=None):
self.session = session
self.mgr = manager_factory.for_session(session)

def lookup_user(self, username):
"""
Load the user and account for the given username, includes credentials and source account
:param username:
:return: (IndentityContext object, credential_list tuple)
"""
usr = self.mgr.get_user(username)

ident = IdentityContext(username=username,
user_account=usr['account_name'],
user_account_type=usr['account']['type'],
user_account_active=usr['account']['is_active'])

creds = [Credential(type=x[0], value=x[1]['value']) for x in usr.get('credentials', {}).items()]

return ident, creds

def lookup_account(self, account):
"""
Lookup an account only. Useful for context processing.
:param account:
:return:
"""
return self.mgr.get_account(account)


class IdentityProviderFactory(object):
def __init__(self, idp_cls):
self.idp_cls = idp_cls

def for_session(self, session):
return self.idp_cls(session)


idp_factory = IdentityProviderFactory(IdentityProvider)

0 comments on commit 3fef0b7

Please sign in to comment.