Replaced the existing Dockerfiles. Tidied up Readme

I replaced the Dockerfiles that existed, which pulled anchor
down from git with a single Dockerfile that uses the local version
of anchor.

This makes testing local changes to anchor very simple.

I also updated the README to reflect these changes and fixed the
varying line lenghts within that file.

Change-Id: I313c840f594639e6c92ed6ff067da79652b74ed0
This commit is contained in:
Robert Clark 2016-01-13 13:19:19 -06:00
parent c917306533
commit 1c584f8569
5 changed files with 123 additions and 191 deletions

14
Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM python:2.7
RUN pip install pecan
ADD . /code
WORKDIR /code
RUN pip install -e .
RUN openssl req -out CA/root-ca.crt \
-keyout CA/root-ca-unwrapped.key \
-newkey rsa:4096 \
-subj "/CN=Anchor Test CA" \
-nodes \
-x509 \
-days 365
RUN chmod 0400 CA/root-ca-unwrapped.key
ENTRYPOINT ["pecan", "serve", "/code/config.py"]

View File

@ -1,33 +0,0 @@
FROM openstacksecurity/anchor:base
# According to http://crosbymichael.com/dockerfile-best-practices-take-2.html
# Rolling your own python base is in line with probably best practice
MAINTAINER Robert Clark <hyakuhei@gmail.com>
# Clone our repo
# Users may want to use --no-cache to ensure that when building the container
# an up to date version of Anchor is cloned.
WORKDIR /root
RUN git clone git://git.openstack.org/openstack/anchor
WORKDIR /root/anchor
RUN pip install -e .
RUN cp config.py /home/anchor/ ;\
cp config.json /home/anchor/ ;\
chown anchor:anchor /home/anchor/config.py ;\
chown anchor:anchor /home/anchor/config.json
RUN su - anchor
WORKDIR /home/anchor
RUN mkdir CA
RUN openssl req -out CA/root-ca.crt \
-keyout CA/root-ca-unwrapped.key \
-newkey rsa:4096 \
-subj "/CN=Anchor Test CA" \
-nodes \
-x509 \
-days 365 ;\
chmod 0400 CA/root-ca-unwrapped.key
ENTRYPOINT ["/usr/local/bin/pecan", "serve", "/home/anchor/config.py"]

View File

@ -1,37 +0,0 @@
FROM ubuntu:latest
MAINTAINER Robert Clark <hyakuhei@gmail.com>
# root user operations
# Upgrade the base and install required packages
RUN apt-get update && apt-get install -y \
python-dev \
libssl-dev \
libffi-dev \
python-pip \
git
# Clone Anchor, install required python packages
# Setup a user to run anchor
WORKDIR /root
RUN git clone git://git.openstack.org/openstack/anchor
WORKDIR /root/anchor
RUN pip install -e .
RUN adduser --disabled-password --gecos '' anchor
# anchor user operations
RUN cp config.py /home/anchor/
RUN cp config.json /home/anchor/
RUN chown anchor:anchor /home/anchor/config.py
RUN chown anchor:anchor /home/anchor/config.json
RUN su - anchor
WORKDIR /home/anchor
RUN mkdir CA
RUN openssl req -out CA/root-ca.crt \
-keyout CA/root-ca-unwrapped.key \
-newkey rsa:4096 \
-subj "/CN=Anchor Test CA" \
-nodes \
-x509 \
-days 365
RUN chmod 0400 CA/root-ca-unwrapped.key
ENTRYPOINT ["/usr/local/bin/pecan", "serve", "/home/anchor/config.py"]

228
README.md
View File

@ -8,17 +8,20 @@ The validity period can be set in the config file with hour resolution.
Ideas behind Anchor Ideas behind Anchor
=================== ===================
A critical capability within PKI is to revoke a certificate - to ensure that it A critical capability within PKI is to revoke a certificate - to ensure
is no longer trusted by any peer. Unfortunately research has demonstrated that that it is no longer trusted by any peer. Unfortunately research has
the two typical methods of revocation (Certificate Revocation Lists and Online demonstrated that the two typical methods of revocation (Certificate
Certificate Status Protocol) both have failings that make them unreliable, Revocation Lists and Online Certificate Status Protocol) both have
especially when attempting to leverage PKI outside of web-browser software. failings that make them unreliable, especially when attempting to
leverage PKI outside of web-browser software.
Through the use of short-lifetime certificates Anchor introduces the concept of Through the use of short-lifetime certificates Anchor introduces the
"passive revocation". By issuing certificates with lifetimes measured in hours, concept of "passive revocation". By issuing certificates with lifetimes
revocation can be achieved by simply not re-issuing certificates to clients. measured in hours, revocation can be achieved by simply not re-issuing
certificates to clients.
The benefits of using Anchor instead of manual long-term certificates are: The benefits of using Anchor instead of manual long-term certificates
are:
* quick certificate revoking / rotation * quick certificate revoking / rotation
* always tested certificate update mechanism (used daily) * always tested certificate update mechanism (used daily)
@ -29,47 +32,48 @@ The benefits of using Anchor instead of manual long-term certificates are:
Installation Installation
============ ============
In order to install Anchor from source, the following system dependencies need In order to install Anchor from source, the following system
to be present: dependencies need to be present:
* python 2.7 * python 2.7
* python (dev files) * python (dev files)
* libffi (dev) * libffi (dev)
* libssl (dev) * libssl (dev)
When everything is in place, Anchor can be installed in one of three ways. For When everything is in place, Anchor can be installed in one of three
development with virtualenv, run: ways. For development with virtualenv, run:
virtualenv .venv virtualenv .venv
source .venv/bin/activate source .venv/bin/activate
pip install . pip install .
For installing in production, either install a perpared system package, or For installing in production, either install a perpared system package,
install globally in the system: or install globally in the system:
python setup.py install python setup.py install
Running the service Running the service
=================== ===================
In order to run the service, it needs to be started via the `pecan` application In order to run the service, it needs to be started via the `pecan`
server. The only extra parameter is a config file: application server. The only extra parameter is a config file:
pecan serve config.py pecan serve config.py
For development, an additional `--reload` parameter may be used. It will cause For development, an additional `--reload` parameter may be used. It will
the service to reload every time a source file is changed, however it requires cause the service to reload every time a source file is changed, however
installing an additional `watchdog` python module. it requires installing an additional `watchdog` python module.
In the default configuration, Anchor will wait for web requests on port 5000 on In the default configuration, Anchor will wait for web requests on port
local network interface. This can be adjusted in the `config.py` file. 5016 on local network interface. This can be adjusted in the `config.py`
file.
Preparing a test environment Preparing a test environment
============================ ============================
In order to test Anchor with the default configuration, the following can be In order to test Anchor with the default configuration, the following
done to create a test CA. The test certificate can be then used to sign the new can be done to create a test CA. The test certificate can be then used
certificates. to sign the new certificates.
openssl req -out CA/root-ca.crt -keyout CA/root-ca-unwrapped.key \ openssl req -out CA/root-ca.crt -keyout CA/root-ca-unwrapped.key \
-newkey rsa:4096 -subj "/CN=Anchor Test CA" -nodes -x509 -days 365 -newkey rsa:4096 -subj "/CN=Anchor Test CA" -nodes -x509 -days 365
@ -81,127 +85,109 @@ Next, a new certificate request may be generated:
-keyout anchor-test.example.com.key -newkey rsa:2048 \ -keyout anchor-test.example.com.key -newkey rsa:2048 \
-subj "/CN=anchor-test.example.com" -subj "/CN=anchor-test.example.com"
That reqest can be submitted using curl (while `pecan serve config.py` is That reqest can be submitted using curl (while `pecan serve config.py`
running): is running):
curl http://0.0.0.0:5000/v1/sign/default -F user='myusername' \ curl http://0.0.0.0:5016/v1/sign/default -F user='myusername' \
-F secret='simplepassword' -F encoding=pem \ -F secret='simplepassword' -F encoding=pem \
-F 'csr=<anchor-test.example.com.csr' -F 'csr=<anchor-test.example.com.csr'
This will result in the signed request being created in the `certs` directory. This will result in the signed request being created in the `certs`
directory.
Docker test environment Docker test environment
======================= =======================
We have prepared a base docker container for Anchor and a Dockerfile that will We have provided a Dockerfile that can be used to build a container that
install the latest upstream version of Anchor and start the service. These will run anchor
instructions expect the reader to have a working Docker install already.
Docker should *not* be used to serve Anchor in any production environments. These instructions expect the reader to have a working Docker install
already. Docker should *not* be used to serve Anchor in any production
environments.
We use two Dockerfiles for Anchor. "Dockerfile.anchorbase" is a custom image, Assuming you are already in the anchor directory, build a container
built on ubuntu that has lots of libraries and requirements installed in order called 'anchor' that runs the anchor service, with any local changes
to quickly test anchor changes and build into CI processes. "Dockerfile.ubuntu" that have been made in the repo:
is used to build a complete Anchor stack, based on the latest available ubuntu
docker image.
Fetch the most recent version of the Dockerfile.ubuntu: docker build -t anchor .
git clone -n git://git.openstack.org/openstack/anchor --depth 1 To start the service in the container and serve Anchor on port 8080:
cd anchor
git checkout HEAD Dockerfile.ubuntu
Build a new Anchor container image using the Dockerfile: docker run -p 8080:5016 anchor
docker build -t anchor-dev -f Dockerfile.ubuntu . The anchor application should be accessible on port 8080. If you are
running docker natively on Linux, that will be 8080 on localhost
[Optional] If you have previously built a container using the Dockerfile it will contain (127.0.0.1). If you are running docker under Microsoft Windows or Apple
a cached version of the Anchor source code. If you require the latest version OSX it will be running in a docker machine. To find the docker machine
of anchor, build using the --no-cache option: IP address run:
docker build --no-cache -t anchor-dev -f Dockerfile.ubuntu .
Start the service in the container and serve Anchor on port 8080:
docker run -p 8080:5000 anchor-dev
The anchor application should be accessible on port 8080. If you are running
docker natively on Linux, that will be 8080 on localhost (127.0.0.1). If you
are running docker under Microsoft Windows or Apple OSX it will be running in
a docker machine. To find the docker machine IP address run:
docker-machine ip default docker-machine ip default
Docker development environment
==============================
Users who want to quickly test out changes to Anchor or who want to experiment
in other ways may find it more convenient to use Dockerfile.anchorbase file.
The instructions are very similar to using the ubuntu base as described above.
Simply replace "Dockerfile.ubuntu" with "Dockerfile.anchorbase" in the above
instructions.
Running Anchor in production Running Anchor in production
============================ ============================
Anchor shouldn't be exposed directly to the network. It's running via an Anchor shouldn't be exposed directly to the network. It's running via an
application server (Pecan) and doesn't have all the features you'd normally application server (Pecan) and doesn't have all the features you'd
expect from a http proxy - for example dealing well with deliberately slow normally expect from a http proxy - for example dealing well with
connections, or using multiple workers. Anchor can however be run in production deliberately slow connections, or using multiple workers. Anchor can
using a better frontend. however be run in production using a better frontend.
To run Anchor using uwsgi you can use the following command: To run Anchor using uwsgi you can use the following command:
uwsgi --http-socket :5000 --venv path/to/venv --pecan config.py -p 4 uwsgi --http-socket :5016 --venv path/to/venv --pecan config.py -p 4
In case a more complex scripted configuration is needed, for example to handle In case a more complex scripted configuration is needed, for example to
custom headers, rate limiting, or source filtering a complete HTTP proxy like handle custom headers, rate limiting, or source filtering a complete
Nginx may be needed. This is however out of scope for Anchor project. You can HTTP proxy like Nginx may be needed. This is however out of scope for
read more about production deployment in Anchor project. You can read more about production deployment in
[Pecan documentation](http://pecan.readthedocs.org/en/latest/deployment.html). [Pecan documentation](http://pecan.readthedocs.org/en/latest/deployment.html).
Additionally, using an AppArmor profile for Anchor is a good idea to prevent Additionally, using an AppArmor profile for Anchor is a good idea to
exploits relying on one of the native libraries used by Anchor (for example prevent exploits relying on one of the native libraries used by Anchor
OpenSSL). This can be done with sample profiles which you can find in the (for example OpenSSL). This can be done with sample profiles which you
`tools/apparmor.anchor_*` files. The used file needs to be reviewed and updated can find in the `tools/apparmor.anchor_*` files. The used file needs to
with the right paths depending on the deployment location. be reviewed and updated with the right paths depending on the deployment
location.
Validators Validators
========== ==========
One of the main features of Anchor are the validators which make sure that all One of the main features of Anchor are the validators which make sure
requests match a given set of rules. They're configured in `config.json` and that all requests match a given set of rules. They're configured in
the sample configuration includes a few of them. `config.json` and the sample configuration includes a few of them.
Each validator takes a dictionary of options which provide the specific Each validator takes a dictionary of options which provide the specific
matching conditions. matching conditions.
Currently available validators are: Currently available validators are:
* `common_name` ensures CN matches one of names in `allowed_domains` or ranges * `common_name` ensures CN matches one of names in `allowed_domains` or
in `allowed_networks` ranges in `allowed_networks`
* `alternative_names` ensures alternative names match one of the names in * `alternative_names` ensures alternative names match one of the names
`allowed_domains` in `allowed_domains`
* `alternative_names_ip` ensures alternative names match one of the names in * `alternative_names_ip` ensures alternative names match one of the
`allowed_domains` or IP ranges in `allowed_networks` names in `allowed_domains` or IP ranges in `allowed_networks`
* `blacklist_names` ensures CN and alternative names do not contain any of the * `blacklist_names` ensures CN and alternative names do not contain any
configured `domains` of the configured `domains`
* `server_group` ensures the group the requester is contained within * `server_group` ensures the group the requester is contained within
`group_prefixes` `group_prefixes`
* `extensions` ensures only `allowed_extensions` are present in the request * `extensions` ensures only `allowed_extensions` are present in the
request
* `key_usage` ensures only `allowed_usage` is requested for the certificate * `key_usage` ensures only `allowed_usage` is requested for the
certificate
* `ca_status` ensures the request does/doesn't require the CA flag * `ca_status` ensures the request does/doesn't require the CA flag
* `source_cidrs` ensures the request comes from one of the ranges in `cidrs` * `source_cidrs` ensures the request comes from one of the ranges in
`cidrs`
A configuration entry for a validator might look like one from the sample A configuration entry for a validator might look like one from the
config: sample config:
"key_usage": { "key_usage": {
"allowed_usage": [ "allowed_usage": [
@ -214,11 +200,11 @@ config:
Authentication Authentication
============== ==============
Anchor can use one of the following authentication modules: static, keystone, Anchor can use one of the following authentication modules: static,
ldap. keystone, ldap.
Static: Username and password are present in `config.json`. This mode should be Static: Username and password are present in `config.json`. This mode
used only for development and testing. should be used only for development and testing.
"auth": { "auth": {
"static": { "static": {
@ -227,8 +213,8 @@ used only for development and testing.
} }
} }
Keystone: Username is ignored, but password is a token valid in the configured Keystone: Username is ignored, but password is a token valid in the
keystone location. configured keystone location.
"auth": { "auth": {
"keystone": { "keystone": {
@ -236,10 +222,11 @@ keystone location.
} }
} }
LDAP: Username and password are used to bind to an LDAP user in a configured LDAP: Username and password are used to bind to an LDAP user in a
domain. User's groups for the `server_group` filter are retrieved from configured domain. User's groups for the `server_group` filter are
attribute `memberOf` in search for `(sAMAccountName=username@domain)`. The retrieved from attribute `memberOf` in search for
search is done in the configured base. `(sAMAccountName=username@domain)`. The search is done in the configured
base.
"auth": { "auth": {
"ldap": { "ldap": {
@ -254,16 +241,16 @@ search is done in the configured base.
Signing backends Signing backends
================ ================
Anchor allows the use of configurable signing backend. While it provides one Anchor allows the use of configurable signing backend. While it provides
implementation (based on cryptography.io and OpenSSL), other implementations one implementation (based on cryptography.io and OpenSSL), other
may be configured. implementations may be configured.
The resulting certificate is stored locally if the `output_path` is set to any The resulting certificate is stored locally if the `output_path` is set
string. This does not depend on the configured backend. to any string. This does not depend on the configured backend.
Backends can specify their own options - please refer to the backend Backends can specify their own options - please refer to the backend
documentation for the specific list. The default backend takes the following documentation for the specific list. The default backend takes the
options: following options:
* `cert_path`: path where local CA certificate can be found * `cert_path`: path where local CA certificate can be found
@ -288,12 +275,13 @@ For more information, please refer to the documentation.
Fixups Fixups
====== ======
Anchor can modify the submitted CSRs in order to enforce some rules, remove Anchor can modify the submitted CSRs in order to enforce some rules,
deprecated elements, or just add information. Submitted CSR may be modified or remove deprecated elements, or just add information. Submitted CSR may
entirely redone. Fixup are loaded from "anchor.fixups" namespace and can take be modified or entirely redone. Fixup are loaded from "anchor.fixups"
parameters just like validators. namespace and can take parameters just like validators.
Reporting bugs and contributing Reporting bugs and contributing
=============================== ===============================
For bug reporting and contributing, please check the CONTRIBUTING.md file. For bug reporting and contributing, please check the CONTRIBUTING.md
file.

View File

@ -1,5 +1,5 @@
server = { server = {
'port': '5000', 'port': '5016',
'host': '0.0.0.0' 'host': '0.0.0.0'
} }