1. 生成rsa 配对的公钥私钥
openssl genrsa -out ./private_key.pem 4096 openssl req -new -x509 -key ./private_key.pem -out ./root.crt -days 3650 -subj /C=CN/ST=state/L=CN/O=cloverstd/OU=cloverstd\ unit/CN=hui.lu/emailAddress=xingyue@staff.sina.com.cn
2. pull registry v2
docker pull registry:2.1.1
3. 修改配置文件config.yml
version: 0.1 log: level: debug fields: service: registry environment: development storage: cache: layerinfo: inmemory filesystem: rootdirectory: /tmp/registry-dev maintenance: uploadpurging: enabled: false http: addr: :5000 secret: asecretforlocaldevelopment debug: addr: localhost:5001 auth: token: issuer: registry-token-issuer realm: http://192.168.122.186:8080/service/token rootcertbundle: /etc/registry/root.crt service: token-service redis: addr: localhost:6379 pool: maxidle: 16 maxactive: 64 idletimeout: 300s dialtimeout: 10ms readtimeout: 10ms writetimeout: 10ms notifications: endpoints: - name: local-8082 url: http://localhost:5003/callback headers: Authorization: [Bearer <an example token>] timeout: 1s threshold: 10 backoff: 1s disabled: true - name: local-8083 url: http://localhost:8083/callback timeout: 1s threshold: 10 backoff: 1s disabled: true
4. 重新编译生成新的auth_registy:
FROM docker.io/registry:2.0 COPY config.yml /go/src/github.com/docker/distribution/cmd/registry/config.yml
5. 启动docker registry
[/shell]
docker run -d -p 5000:5000 -v /opt/registry:/var/lib/registry -v `pwd`/root.crt:/etc/registry/root.crt:ro auth_registry
[/shell]
6.添加认证的python脚本:
from flask import Flask, request, jsonify, make_response, json import base64 import jwt from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat, load_pem_private_key import time import os import hashlib app = Flask(__name__) SERVICE = 'token-service' ISSUER = 'registry-token-issuer' class DockerRegistryAuth(object): def __init__(self, account, scopes, service, issuer, private_key_path, token_expires=300): self.account = account self.issuer = issuer self.scopes = scopes self.access = self.get_access_by_scopes(scopes) self.service = service self.private_key_path = private_key_path self.token_expires = token_expires @property def private_key(self): if getattr(self, '_private_key_content', None): return self._private_key_content with open(self.private_key_path, 'r') as fp: setattr(self, '_private_key_content', fp.read()) return self._private_key_content @property def public_key(self): private_key = load_pem_private_key( self.private_key, password=None, backend=default_backend() ) _public_key = private_key.public_key() return _public_key def check_service(self, service): return self.service == service def get_token(self): now = int(time.time()) claim = { 'iss': self.issuer, 'sub': self.account, 'aud': self.service, 'exp': now + self.token_expires, 'nbf': now, 'iat': now, 'jti': base64.b64encode(os.urandom(1024)), 'access': self.access } headers = { 'kid': self.get_kid() } token = jwt.encode(claim, self.private_key, algorithm='RS256', headers=headers) return { 'token': token, 'issued_at': now, 'expires_in': now + self.token_expires } def get_kid(self): der_public_key = self.public_key.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo) sha256 = hashlib.sha256(der_public_key) base32_payload = base64.b32encode(sha256.digest()[:30]) # 240bits / 8 return ":".join( [base32_payload[i:i+4] for i in xrange(0, 48, 4)] ) def get_login_info(self, authorization): if not authorization: return None auth_info = authorization if authorization.startswith('Basic'): auth_info = authorization[5:] user_info = base64.b64decode(auth_info) self.username, self.password = user_info.split(':') return { 'username': self.username, 'password': self.password, } def get_access_by_scopes(self, scopes): access = list() if not scopes: return access for scope in scopes: type_, name, actions = scope.split(':') access.append({ 'type': type_, 'name': name, 'actions': actions.split(',') }) return access def unauthorized401(access, message=None, code=None): detail = list() for scope in access: for action in scope['actions']: detail.append({ "Action": action, "Name": scope['name'], "Type": scope['type'] }) data = { "errors": [ { "code": code or "UNAUTHORIZED", "detail": detail, "message": message or "access to the requested resource is not authorized" } ] } resp = make_response(json.dumps(data), 401) resp.headers['Content-Type'] = 'application/json; charset=utf-8' resp.headers['Docker-Distribution-Api-Version'] = 'registry/2.0' resp.headers['Www-Authenticate'] = 'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull,push"' return resp @app.route('/service/token') def service_token(): print request.headers scopes = request.args.getlist('scope') account = request.args.get('account') client_id = request.args.get('client_id') service = request.args.get('service') http_base_auth = request.headers.get('Authorization') registry_auth = DockerRegistryAuth(account, scopes, SERVICE, ISSUER, './private_key.pem') if not registry_auth.check_service(service): return unauthorized401(registry_auth.access, 'service not be allowed.') user = registry_auth.get_login_info(http_base_auth) if user: if not (user['username'] == 'test' and user['password'] == 'test'): return unauthorized401(registry_auth.access, 'incorrect username or password') res = registry_auth.get_token() return jsonify( token=res['token'], ) return unauthorized401(registry_auth.access) if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True)
7.安装需要的包:
pip install PyJWT
8. 启动认证脚本:
python auth.py
9. 测试登录:
docker login localhost:5000
test:test:x@s.com
然后成功获得token 则登录成功.
Maybe you like these: |
用jquery实现下拉列表的联动 |
大海,誓言 |
再见青春 |
哪一站【突然感觉,现在的心情跟现在好像呢】 |
如果可以,请在42.195公里之后等我 |
无觅 |