Skip to content

Commit 51f58e6

Browse files
committed
Overhaul docs and switch to container based proxy
1 parent 6770e05 commit 51f58e6

File tree

14 files changed

+469
-355
lines changed

14 files changed

+469
-355
lines changed

Dockerfile

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM busybox:ubuntu-14.04
2+
3+
MAINTAINER Cory Thomas <[email protected]>
4+
5+
COPY docker-ec2-metadata /bin/ec2metaproxy
6+
7+
ENTRYPOINT ["/bin/ec2metaproxy"]

Makefile

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
export GOPATH=$(CURDIR)
22

3+
DOCKER_IMAGE=dump247/ec2metaproxy
4+
35
SRC_DIRS=github.com/dump247/docker-ec2-metadata
46
CMD_DIRS=github.com/dump247/docker-ec2-metadata
57

6-
.PHONY: clean build test compile fmt rpm
8+
.PHONY: clean build test compile fmt docker-image
79

810
build: fmt test compile
911

@@ -21,8 +23,10 @@ clean:
2123
rm -rf ${GOPATH}/bin
2224
rm -rf ${GOPATH}/pkg
2325

24-
rpm:
25-
mkdir -p ${GOPATH}/pkg/rpm/service/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
26-
rpmbuild -bb --define "_topdir ${GOPATH}/pkg/rpm/service" ${GOPATH}/rpm/service.spec
27-
mkdir -p ${GOPATH}/bin
28-
cp ${GOPATH}/pkg/rpm/service/RPMS/x86_64/* bin
26+
docker-image: clean
27+
docker run --rm -v ${GOPATH}:/project -w=/project golang:1.5 make
28+
@cp Dockerfile bin/
29+
docker build -t ${DOCKER_IMAGE} bin/
30+
31+
push-docker-image: docker-image
32+
docker push ${DOCKER_IMAGE}

README.md

+26-162
Original file line numberDiff line numberDiff line change
@@ -1,183 +1,47 @@
11
A service that runs on an EC2 instance that proxies the EC2 instance metadata service
2-
for docker containers. The proxy overrides metadata endpoints for individual docker
2+
for linux containers. The proxy overrides metadata endpoints for individual
33
containers.
44

5+
The following container platforms are supported:
6+
7+
* [docker](https://www.docker.com)
8+
* [flynn](https://flynn.io)
9+
510
At this point, the only endpoint overridden is the security credentials. This allows
611
for different containers to have different IAM permissions and not just use the permissions
712
provided by the instance profile. However, this same technique could be used to override
813
any other endpoints where appropriate.
914

10-
# Build
11-
12-
Requires:
13-
14-
* golang 1.2+
15-
* make
15+
The proxy works by mapping the metadata source request IP to the container using the container
16+
platform specific API. The container's metadata contains information about what IAM permissions
17+
to use. Therefore, the proxy does not work for containers that do not use the container
18+
network bridge (for example, containers using "host" networking).
1619

17-
The dependencies are managed with git submodules. After cloning, make sure to initialize the submodules:
18-
19-
```bash
20-
# Either initialize submodules when you clone the repo
21-
git clone --recursive [email protected]:dump247/docker-ec2-metadata.git
22-
23-
# Or, if you have already cloned, initialize the submodules
24-
git submodule update --init --recursive
25-
```
20+
# Setup
2621

27-
Run `make` or `make build`. The resulting executable will be in `bin/`.
22+
## Host
2823

29-
Run `make clean` to clear out any build artifacts.
24+
The host EC2 instance must have firewall settings that redirect any EC2 metadata connections
25+
from containers to the metadata proxy. The proxy will then process the request and
26+
may forward the request to the real metadata service.
3027

31-
## RPM
28+
The instance profile of the host EC2 instance must also have permission to assume the IAM roles
29+
for the containers.
3230

33-
Requires:
31+
See:
3432

35-
* rpm-build
33+
* [Host Setup](docs/host-setup.md)
3634

37-
1. Run `make` to create the executable
38-
2. Run `make rpm` to build the rpm
35+
## Containers
3936

40-
The steps can all be performed at once with `make build rpm` or `make clean build rpm`.
37+
Containers do not require any changes or modifications to utilize the metadata proxy. By
38+
default, they will receive the default permissions configured by the proxy. Alternatively,
39+
a container can be configured to use a separate IAM role or provide an IAM policy.
4140

42-
# Setup
41+
See:
4342

44-
What is needed is an EC2 instance with assume role permissions and one or more roles defined
45-
that it can assume. The roles will be used by the containers to acquire their own permissions.
46-
47-
## Permissions
48-
49-
The EC2 instance must have permission to assume the roles required by the docker containers.
50-
51-
Note that assuming a role is two way: the permission to assume roles has to be granted to the
52-
instance profile and the role has to allow the instance profile to assume it.
53-
54-
There must be at least one role to use as the default role if the container has not specified
55-
one. The default role can have empty permissions (zero access) or some set of standard
56-
permissions.
57-
58-
Example CloudFormation:
59-
60-
* _DockerContainerRole1_ is the set of permissions for a docker container
61-
* _InstanceRole_ is the role used by the EC2 instance profile and needs permission to assume _DockerContainerRole1_
62-
63-
```json
64-
{
65-
"AWSTemplateFormatVersion": "2010-09-09",
66-
"Resources": {
67-
"DockerContainerRole1": {
68-
"Type": "AWS::IAM::Role",
69-
"Properties": {
70-
"AssumeRolePolicyDocument": {
71-
"Statement": [
72-
{
73-
"Effect": "Allow",
74-
"Principal": {
75-
"AWS": [ {"Fn::GetAtt" : ["InstanceRole", "Arn"]} ]
76-
},
77-
"Action": [ "sts:AssumeRole" ]
78-
}
79-
]
80-
},
81-
"Path": "/docker/",
82-
"Policies": []
83-
}
84-
},
85-
86-
"InstanceRole": {
87-
"Type": "AWS::IAM::Role",
88-
"Properties": {
89-
"AssumeRolePolicyDocument": {
90-
"Statement": [
91-
{
92-
"Effect": "Allow",
93-
"Principal": {
94-
"Service": [ "ec2.amazonaws.com" ]
95-
},
96-
"Action": [ "sts:AssumeRole" ]
97-
}
98-
]
99-
},
100-
"Path": "/",
101-
"Policies": [
102-
{
103-
"PolicyName": "AssumeRoles",
104-
"PolicyDocument": {
105-
"Statement": [
106-
{
107-
"Effect": "Allow",
108-
"Resource": {"Fn::Join": ["", ["arn:aws:iam::", {"Ref": "AWS::AccountId"}, ":role/docker/*"]]},
109-
"Action": [ "sts:AssumeRole" ]
110-
}
111-
]
112-
}
113-
}
114-
]
115-
}
116-
},
117-
118-
"InstanceProfile": {
119-
"Type": "AWS::IAM::InstanceProfile",
120-
"Properties": {
121-
"Path": "/",
122-
"Roles": [{"Ref": "InstanceRole"}]
123-
}
124-
}
125-
}
126-
}
127-
```
128-
129-
## Instance Setup
130-
131-
Install docker and run with the standard unix domain socket (_/var/run/docker.sock_).
132-
133-
Setup a rule to route all metadata service traffic from the containers
134-
to the proxy service. By default, the proxy runs on _0.0.0.0:18000_, but this can
135-
be overridden. Be careful that you do not expose the service outside the EC2 instance!
136-
137-
This script will setup the routing rules. You may need to adjust if you make changes
138-
to how docker sets up its networking. If you are an iptables ninja and can improve this,
139-
please submit a ticket or a pull request!
140-
141-
```bash
142-
# Get the host IP address. You can use a different mechanism if you wish.
143-
# Note that IP can not be 127.0.0.1 because DNAT for loopback is not possible.
144-
PROXY_IP=$(ifconfig eth0 | grep -Eo "inet addr:[0-9.]+" | grep -Eo "[0-9.]+")
145-
146-
# Port that the proxy service runs on. Default is 18000.
147-
PROXY_PORT=18000
148-
149-
# Drop any traffic to the proxy service that is NOT coming from docker containers
150-
iptables \
151-
-I INPUT \
152-
-p tcp \
153-
--dport ${PROXY_PORT} \
154-
! -i docker0 \
155-
-j DROP
156-
157-
# Redirect any requests from docker containers to the proxy service
158-
iptables \
159-
-t nat \
160-
-I PREROUTING \
161-
-p tcp \
162-
-d 169.254.169.254 --dport 80 \
163-
-j DNAT \
164-
--to-destination ${PROXY_IP}:${PROXY_PORT} \
165-
-i docker0
166-
```
167-
168-
## Run the Service
169-
170-
The proxy service will need to run as root or as a user in the _docker_ group.
171-
172-
# Container Role
173-
174-
If the container does not specify a role, the default role is used. A container can specify
175-
a specific role to use by setting the `IAM_ROLE` environment variable.
176-
177-
Example: `IAM_ROLE=arn:aws:iam::123456789012:role/CONTAINER_ROLE_NAME`
178-
179-
Note that the host machine’s instance profile must have permission to assume the given role.
180-
If not, the container will receive an error when requesting the credentials.
43+
* [Docker Container Setup](docs/docker-container-setup.md)
44+
* [Flynn Container Setup](docs/flynn-container-setup.md)
18145

18246
# License
18347

docs/docker-container-setup.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
By default, a container receives the default permissions configured by the metadata
2+
proxy. However, some containers require more or less permissions. For these cases, the
3+
container can provide a custom IAM role, a custom IAM policy, or both.
4+
5+
# Container Role
6+
7+
A container can specify a specific role to use by setting the `IAM_ROLE` environment
8+
variable on the image or the container. The metadata proxy will return credentials
9+
for the given role when requested.
10+
11+
Example:
12+
13+
```bash
14+
docker run -e 'IAM_ROLE=arn:aws:iam::123456789012:role/ContainerRoleName' ...
15+
```
16+
17+
Note that the host machine’s instance profile must have permission to assume the given role.
18+
If not, the container will receive an error when requesting the credentials.
19+
20+
# Container Policy
21+
22+
A container can specify a custom IAM policy by setting the `IAM_POLICY` environment
23+
variable on the image or the container. The resulting container permissions will be
24+
the intersection of the custom policy and the default container role or the role
25+
specified by the container's `IAM_ROLE` environment variable.
26+
27+
Example:
28+
29+
```bash
30+
docker run -e 'IAM_POLICY={"Version":"2012-10-17","Statement":{"Effect":"Allow","Resource":"*","Action":"ec2:*"}}' ...
31+
```

docs/flynn-container-setup.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
By default, a job receives the default permissions configured by the metadata
2+
proxy. However, some jobs require more or less permissions. For these cases, the
3+
job can provide a custom IAM role, a custom IAM policy, or both.
4+
5+
# Job Role
6+
7+
A job can specify a specific role to use by setting the `IAM_ROLE` metadata
8+
variable. The metadata proxy will return credentials for the given role when
9+
requested.
10+
11+
Example:
12+
13+
```bash
14+
flynn meta set 'IAM_ROLE=arn:aws:iam::123456789012:role/JobRoleName'
15+
```
16+
17+
Note that the host machine’s instance profile must have permission to assume the given role.
18+
If not, the job will receive an error when requesting the credentials.
19+
20+
# Job Policy
21+
22+
A job can specify a custom IAM policy by setting the `IAM_POLICY` metadata
23+
variable. The resulting job permissions will be
24+
the intersection of the custom policy and the default container role or the role
25+
specified by the job's `IAM_ROLE` metdata variable.
26+
27+
Example:
28+
29+
```bash
30+
flynn meta set 'IAM_POLICY={"Version":"2012-10-17","Statement":{"Effect":"Allow","Resource":"*","Action":"ec2:*"}}'
31+
```

0 commit comments

Comments
 (0)