Skip to content

Instantly share code, notes, and snippets.

@osterman
Created November 14, 2018 22:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save osterman/55edc4af91370f2ff1327af8b434c6fa to your computer and use it in GitHub Desktop.
Save osterman/55edc4af91370f2ff1327af8b434c6fa to your computer and use it in GitHub Desktop.
Docker Registry Authentication Proxy
var http = require('http'),
https = require('https'),
buffer = require('buffer'),
httpProxy = require('http-proxy');
var tokens = {},
basicAuth = new Buffer(process.env.BASIC_AUTH).toString('base64');
//
// Create a proxy server with custom application logic
//
var proxy = httpProxy.createProxyServer({ secure: false, changeOrigin: true });
var cacheToken = function(req, rep) {
var token, tokenParts, signature, repository, access, key;
if (typeof rep.headers['x-docker-token'] === 'string') {
// signature=2284514fb61ddc0d9a9f87eada51c36831b3f9b5,repository="xxxx/xxxx",access=read
token = rep.headers['x-docker-token'];
tokenParts = token.split(',');
if(tokenParts.length === 3) {
signature = tokenParts[0];
repository = (tokenParts[1].split('"'))[1];
access = (tokenParts[2].split('"'))[1];
key = req.headers['host'] + '/' + repository;
console.log('AUTH ' + token);
tokens[key] = token;
}
}
};
var fetchToken = function(req, res) {
var token, key;
}
proxy.on('proxyRes', function (proxyRes, req, res) {
console.log('INFO: resp='+req.url, JSON.stringify(proxyRes.headers, true, 2));
cacheToken(req, proxyRes);
delete proxyRes.headers['x-docker-endpoints'];
res.setHeader('x-docker-endpoints', process.env.REGISTRY_HOST);
});
proxy.on('proxyReq', function(proxyReq, req, res, options) {
console.log('INFO: req='+req.url, JSON.stringify(req.headers, true, 2));
if(req.headers['host'] === process.env.INDEX_HOST) {
proxyReq.setHeader('Authorization', 'Basic ' + basicAuth);
}
if(req.headers['host'] === process.env.REGISTRY_HOST) {
var path, repo, key, token;
path = req.url.split('/');
repo = path[3] + '/' + path[4];
key = req.headers['host'] + '/' + repo;
if(typeof tokens[key] === 'string') {
token = tokens[key];
console.log('Token ' + token);
proxyReq.setHeader('Authorization', 'Token ' + token);
}
}
});
proxy.on('error', function (error, req, res) {
var json;
console.log('ERROR', error);
if (!res.headersSent) {
res.writeHead(500, { 'content-type': 'application/json' });
}
json = { error: 'proxy_error', reason: error.message };
res.end(JSON.stringify(json));
});
var server = http.createServer(function(req, res) {
var endpoint, headers = {};
if(req.headers['host'] === process.env.INDEX_HOST) {
endpoint = 'https://' + process.env.INDEX_UPSTREAM;
}
else if(req.headers['host'] === process.env.REGISTRY_HOST) {
endpoint = 'https://' + process.env.REGISTRY_UPSTREAM;
}
else {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Request failed');
return;
}
proxy.web(req, res, {target: endpoint, headers: headers} );
});
console.log("docker registry auth proxy listening on port 80")
server.listen(80);
@osterman
Copy link
Author

Corresponding Dockerfile

FROM ubuntu:14.04

ENV REGISTRY_UPSTREAM registry-1.docker.io
ENV REGISTRY_HOST registry.xxxx.local
ENV INDEX_UPSTREAM index.docker.io
ENV INDEX_HOST index.xxxx.local
ENV BASIC_AUTH user:pass

WORKDIR /

RUN apt-get update && \
    apt-get -y install node npm && \
    npm install http-proxy

ADD server.js /server.js

ENTRYPOINT ["/usr/bin/nodejs"]

CMD ["/server.js"]

EXPOSE 80

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment