From 582fa84a7d8969d2ca0c72ee99d32deeda9c7191 Mon Sep 17 00:00:00 2001 From: Scott Little Date: Wed, 4 Sep 2019 10:14:27 -0400 Subject: [PATCH] Relocated some packages to repo 'containers' List of relocated subdirectories: kubernetes/registry-token-server Story: 2006166 Task: 35687 Depends-On: I665dc7fabbfffc798ad57843eb74dca16e7647a3 Change-Id: I9a647e264073a27a68885acf2c2014535bea7486 Signed-off-by: Scott Little Depends-On: I7f1c1184e8dfeff1740b695adb71b8becaa4e7b1 --- .../centos/build_srpm.data | 12 - .../files/registry-token-server.service | 19 - .../centos/files/token-server-certificate.pem | 19 - .../centos/files/token-server-private-key.pem | 27 -- .../centos/files/token_server.conf | 1 - .../centos/registry-token-server.spec | 81 ---- .../registry-token-server/src/Gopkg.lock | 85 ---- .../registry-token-server/src/Gopkg.toml | 50 -- kubernetes/registry-token-server/src/LICENSE | 202 -------- .../registry-token-server/src/errors.go | 43 -- .../src/keystone/access.go | 96 ---- kubernetes/registry-token-server/src/main.go | 435 ------------------ kubernetes/registry-token-server/src/token.go | 224 --------- 13 files changed, 1294 deletions(-) delete mode 100644 kubernetes/registry-token-server/centos/build_srpm.data delete mode 100644 kubernetes/registry-token-server/centos/files/registry-token-server.service delete mode 100644 kubernetes/registry-token-server/centos/files/token-server-certificate.pem delete mode 100644 kubernetes/registry-token-server/centos/files/token-server-private-key.pem delete mode 100644 kubernetes/registry-token-server/centos/files/token_server.conf delete mode 100644 kubernetes/registry-token-server/centos/registry-token-server.spec delete mode 100644 kubernetes/registry-token-server/src/Gopkg.lock delete mode 100644 kubernetes/registry-token-server/src/Gopkg.toml delete mode 100644 kubernetes/registry-token-server/src/LICENSE delete mode 100644 kubernetes/registry-token-server/src/errors.go delete mode 100644 kubernetes/registry-token-server/src/keystone/access.go delete mode 100644 kubernetes/registry-token-server/src/main.go delete mode 100644 kubernetes/registry-token-server/src/token.go diff --git a/kubernetes/registry-token-server/centos/build_srpm.data b/kubernetes/registry-token-server/centos/build_srpm.data deleted file mode 100644 index 7f12975c8..000000000 --- a/kubernetes/registry-token-server/centos/build_srpm.data +++ /dev/null @@ -1,12 +0,0 @@ -TAR_NAME="registry-token-server" -SRC_DIR="$PKG_BASE/src" -COPY_LIST=" \ - $FILES_BASE/* \ - $STX_BASE/downloads/Sirupsen-logrus-55eb11d21d2a31a3cc93838241d04800f52e823d.tar.gz \ - $STX_BASE/downloads/docker-distribution-48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89.tar.gz \ - $STX_BASE/downloads/docker-libtrust-fa567046d9b14f6aa788882a950d69651d230b21.tar.gz \ - $STX_BASE/downloads/gophercloud-gophercloud-aa00757ee3ab58e53520b6cb910ca0543116400a.tar.gz \ - $STX_BASE/downloads/gorilla-context-08b5f424b9271eedf6f9f0ce86cb9396ed337a42.tar.gz \ - $STX_BASE/downloads/gorilla-mux-456bcfa82d672db7cae587c9b541463f65bc2718.tar.gz \ -" -TIS_PATCH_VER=1 diff --git a/kubernetes/registry-token-server/centos/files/registry-token-server.service b/kubernetes/registry-token-server/centos/files/registry-token-server.service deleted file mode 100644 index 477e85dfb..000000000 --- a/kubernetes/registry-token-server/centos/files/registry-token-server.service +++ /dev/null @@ -1,19 +0,0 @@ -[Unit] -Description=v2 Registry token server for Docker - -[Service] -Type=simple -EnvironmentFile=/etc/docker-distribution/registry/token_server.conf -ExecStart=/usr/bin/registry-token-server -addr=${REGISTRY_TOKEN_SERVER_ADDR} \ - -issuer=${REGISTRY_TOKEN_SERVER_ISSUER} \ - -endpoint=${REGISTRY_TOKEN_SERVER_KS_ENDPOINT} \ - -tlscert=${REGISTRY_TOKEN_SERVER_TLSCERT} \ - -tlskey=${REGISTRY_TOKEN_SERVER_TLSKEY} \ - -realm=${REGISTRY_TOKEN_SERVER_REALM} \ - -key=${REGISTRY_TOKEN_SERVER_KEY} -Restart=on-failure -ExecStartPost=/bin/bash -c 'echo $MAINPID > /var/run/registry-token-server.pid' -ExecStopPost=/bin/rm -f /var/run/registry-token-server.pid - -[Install] -WantedBy=multi-user.target diff --git a/kubernetes/registry-token-server/centos/files/token-server-certificate.pem b/kubernetes/registry-token-server/centos/files/token-server-certificate.pem deleted file mode 100644 index c40df597b..000000000 --- a/kubernetes/registry-token-server/centos/files/token-server-certificate.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDADCCAegCCQCSevkS4h7LQjANBgkqhkiG9w0BAQsFADBCMQswCQYDVQQGEwJY -WDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBh -bnkgTHRkMB4XDTE4MDkyMTE0MTYwOFoXDTE5MDkyMTE0MTYwOFowQjELMAkGA1UE -BhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwTRGVmYXVsdCBD -b21wYW55IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtCbNJ/ -aPEMkZFEtMKRomOh9NgeOv0jYFY5i23fXghtTgdXu9//H3Huz5/KDJ+XEUp2DZgK -YQ2UHVR+cqj2sFjCllfAVrzmv9FFR0CQpQxqKcxChefVwsMh6XsqF+GzbqzFOx67 -bT39Xb5+spAmDHctFl3nrmyA1wM6e+OXcktC0chILeN+UEyq5Xeng6/BpVnI2UaY -J1OpfuUrffddy5t0oeuKGZ/xG2g9sL6GMGBeVslOmLg4CBOwq3knUGoOTFYSjHVx -rU/p4YgUotIUvb4GBsXqbiI7M2NakItTR6mxfcYiKkxfjadQlptFyGucI84mMYx8 -vO3o6TFLfcTYqZ8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAHXZR0U0pyMkYIeO5 -Y/n0H9Onj/PtCJHBbYzMHZGMPlX2IbW+JAeE/0XNIYGHtAtFwlb825Tkg2p7wpa8 -8HmOBqkTyn2ywDdmPqdfjCiMu/Ge6tkLjqkmYWv2l/d4+qEMR4dUh9g8SrrtUdZg -DP7H22B+0knQ7s04JuiJ27hqi4nPOzdwdJNpz5Przgce8vN1ihk8194pR/uoNrjP -td3Po+DwmxFKigoKPQCHgQuD63mAFor4vVnht+IkNbB3/lQyXP6Qv7DnWVW9WDBL -nKxgXhRwyy5mYebYmwA//JX41O/Kdp1Q6oWgv4zSLd8M9FIMtESG8k4gSl0XfUBa -Y24p0Q== ------END CERTIFICATE----- diff --git a/kubernetes/registry-token-server/centos/files/token-server-private-key.pem b/kubernetes/registry-token-server/centos/files/token-server-private-key.pem deleted file mode 100644 index 4332eb34b..000000000 --- a/kubernetes/registry-token-server/centos/files/token-server-private-key.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAq0Js0n9o8QyRkUS0wpGiY6H02B46/SNgVjmLbd9eCG1OB1e7 -3/8fce7Pn8oMn5cRSnYNmAphDZQdVH5yqPawWMKWV8BWvOa/0UVHQJClDGopzEKF -59XCwyHpeyoX4bNurMU7HrttPf1dvn6ykCYMdy0WXeeubIDXAzp745dyS0LRyEgt -435QTKrld6eDr8GlWcjZRpgnU6l+5St9913Lm3Sh64oZn/EbaD2wvoYwYF5WyU6Y -uDgIE7CreSdQag5MVhKMdXGtT+nhiBSi0hS9vgYGxepuIjszY1qQi1NHqbF9xiIq -TF+Np1CWm0XIa5wjziYxjHy87ejpMUt9xNipnwIDAQABAoIBAFHCIV+QkdHZ9TiL -u1vT2NmFvPTb4b9tfxVK3YRziVmujPy2Zqu2CRYEMzyOYd5iaU/J8g1ujwzDdAkd -YLHHK0MEim+UFBSUeGh4kV6CbzjxCclIzNJz20n6y5MP8ly+o4x5kBLI2YsphPJn -W+mzMGpIrQ/hhgSosX0KE5EAgQDqOfJSlhZvSgSO5UF9nXvEn7Y9Zc8GK0XQdcwB -Pr8iFhuhEJmmb4LrCm+3Me/fhLxFjUAOAcLSkFnqfxo2vAuRqk99OOLxFEfPYZB8 -kLkKlQ+PwhkG3pjPg6w/rOmBHqW/ZEpd87972JWeHscXYpb/cLLVmcJbZI/claos -YOHS7CECgYEA4XKo7GzuqSkLskfaZM2pyNhHbxphqyNfk8GmW5NJnKavpmY8YiXh -7hNXXf4HCkcHvHMn4JUCHgHVavDNhNnrHNrQAzO3KwuUrrFiBP+yP1tRyQ4BP395 -KIBSUyeEOo9vM7d3yerI8WHboio5gaoqEfeNS1dakZ6ZiOpoP94CIxECgYEAwnfW -Drdcqkpj794gYDlXH4D279f7+qmq11eI4C0zkZzTFkExl8BGfqpy49kruaTm0e4t -L1B23TYfKC0ei4BQskyNCHUnl/eic/JHe9gJRd6BAZi2REfV0LI4ytYGgniCu50H -EJVvTVMXS/+wWcjZr037oV6/WiB9Wzr7Z1oFoa8CgYBlmqdG5lEpK7Z5wqhKheXe -/pozGFCsMGUC0mOHIfoq/3RqKelM0oXgJhdZ5QKHPzvdUojGTmGF5I2qhJwbI5sy -her5hnUmkTGRCaCDYDmVFDLnycgGNg0Ek9CGaWjOe5ZCWI1EEuw83T1++Eiyh14u -esLTEatftXq8megh4IxWAQKBgQCTNfox27ZnJrcuXn0tulpse8jy2RJjt0qfhyET -asRN52SXxTRQhvoWattcBgsmlmEw69cCqSvB23WMiVNFERaFUpO0olMdpBUzJmXc -pzal0IDh/4OCfsqqGDALxCbbX3S/p2gwsp617z+EhYMvBG9dWHAywTGjfVLH3Ady -PmBi+wKBgQCWJS/PmTpyO8LU4MYZk91mJmjHAsPlgi/9n8yEqdmins+X698IsoCr -s2FN8rol8+UP8c3m9o4kp62ouoby2QzAZw0y3UGWcxOb3ZpoozatKodsoETSLLoL -T//wVn2Z2MsS9tLOBLZzsZiYlHyYxTUm7UTOdxdjbSLWVdLbCpKEhg== ------END RSA PRIVATE KEY----- diff --git a/kubernetes/registry-token-server/centos/files/token_server.conf b/kubernetes/registry-token-server/centos/files/token_server.conf deleted file mode 100644 index 4683478c1..000000000 --- a/kubernetes/registry-token-server/centos/files/token_server.conf +++ /dev/null @@ -1 +0,0 @@ -# This is a puppet managed config file diff --git a/kubernetes/registry-token-server/centos/registry-token-server.spec b/kubernetes/registry-token-server/centos/registry-token-server.spec deleted file mode 100644 index 6aa2bf65e..000000000 --- a/kubernetes/registry-token-server/centos/registry-token-server.spec +++ /dev/null @@ -1,81 +0,0 @@ -%if ! 0%{?gobuild:1} -%define gobuild(o:) go build -ldflags "${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n')" -a -v -x %{?**}; -%endif - -Name: registry-token-server -Version: 1.0.0 -Release: 1%{?_tis_dist}.%{tis_patch_ver} -Summary: Token server for use with Docker registry with Openstack Keystone back end -License: ASL 2.0 -Source0: registry-token-server-%{version}.tar.gz -Source1: %{name}.service -Source2: token_server.conf - -# Go dependencies downloaded as tarballs -Source10: Sirupsen-logrus-55eb11d21d2a31a3cc93838241d04800f52e823d.tar.gz -Source11: docker-distribution-48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89.tar.gz -Source12: docker-libtrust-fa567046d9b14f6aa788882a950d69651d230b21.tar.gz -Source13: gophercloud-gophercloud-aa00757ee3ab58e53520b6cb910ca0543116400a.tar.gz -Source14: gorilla-context-08b5f424b9271eedf6f9f0ce86cb9396ed337a42.tar.gz -Source15: gorilla-mux-456bcfa82d672db7cae587c9b541463f65bc2718.tar.gz - -BuildRequires: systemd -Requires(post): systemd -Requires(preun): systemd -Requires(postun): systemd - -BuildRequires: golang >= 1.6 -ExclusiveArch: %{?go_arches:%{go_arches}}%{!?go_arches:%{ix86} x86_64 %{arm}} - -%description -%{summary} - -%prep -%setup -q -n registry-token-server-%{version} - -# Extract other go dependencies -%setup -T -D -a 10 -%setup -T -D -a 11 -%setup -T -D -a 12 -%setup -T -D -a 13 -%setup -T -D -a 14 -%setup -T -D -a 15 -mkdir -p _build/src/github.com/gorilla/ && mv gorilla-mux _build/src/github.com/gorilla/mux -mkdir -p _build/src/github.com/docker/ && mv docker-distribution _build/src/github.com/docker/distribution -mkdir -p _build/src/github.com/docker/ && mv docker-libtrust _build/src/github.com/docker/libtrust -mkdir -p _build/src/github.com/docker/distribution/ && mv gorilla-context _build/src/github.com/docker/distribution/context -mkdir -p _build/src/github.com/Sirupsen/ && mv Sirupsen-logrus _build/src/github.com/Sirupsen/logrus -mkdir -p _build/src/github.com/gophercloud && mv gophercloud-gophercloud _build/src/github.com/gophercloud/gophercloud - -%build -mkdir -p ./_build/src/ -ln -s $(pwd) ./_build/src/registry-token-server -export GOPATH=$(pwd)/_build:%{gopath} - -cd ./_build/src/registry-token-server -%gobuild -o bin/registry-token-server registry-token-server - -%install -install -d -p %{buildroot}%{_bindir} -install -p -m 0755 bin/registry-token-server %{buildroot}%{_bindir} - -# install systemd/init scripts -install -d %{buildroot}%{_unitdir} -install -p -m 644 %{SOURCE1} %{buildroot}%{_unitdir} - -# install directory to install default certificate -install -d -p %{buildroot}%{_sysconfdir}/ssl/private - -# install environment variables file for service file -install -d -p %{buildroot}%{_sysconfdir}/%{name}/registry -install -p -m 644 %{SOURCE2} %{buildroot}%{_sysconfdir}/%{name}/registry - -#define license tag if not already defined -%{!?_licensedir:%global license %doc} - -%files -%doc LICENSE - -%{_bindir}/registry-token-server -%{_unitdir}/%{name}.service -%{_sysconfdir}/%{name}/registry/token_server.conf diff --git a/kubernetes/registry-token-server/src/Gopkg.lock b/kubernetes/registry-token-server/src/Gopkg.lock deleted file mode 100644 index 1aac16461..000000000 --- a/kubernetes/registry-token-server/src/Gopkg.lock +++ /dev/null @@ -1,85 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - digest = "1:9c6c19030ff2899d13cfc7a4dc14ff3f2772395d848aa67580f96e6a58aa405f" - name = "github.com/Sirupsen/logrus" - packages = ["."] - pruneopts = "UT" - revision = "55eb11d21d2a31a3cc93838241d04800f52e823d" - -[[projects]] - digest = "1:e894100bb5cc3b952965c9e7d160ea09cc31469a06d7d4bf5326184a87f5c726" - name = "github.com/docker/distribution" - packages = [ - "context", - "registry/api/errcode", - "registry/auth", - "registry/auth/token", - "uuid", - ] - pruneopts = "UT" - revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89" - version = "v2.6.2" - -[[projects]] - digest = "1:0e229970bd76d6cdef6558f51ae493931485fb086d513bc4e3b80003bcf81f39" - name = "github.com/docker/libtrust" - packages = ["."] - pruneopts = "UT" - revision = "fa567046d9b14f6aa788882a950d69651d230b21" - -[[projects]] - digest = "1:f78f704db2735dd21b8050b305ceb4c98b2d50518730a83fdbead6702a57710e" - name = "github.com/gophercloud/gophercloud" - packages = [ - ".", - "openstack", - "openstack/identity/v2/tenants", - "openstack/identity/v2/tokens", - "openstack/identity/v3/tokens", - "openstack/utils", - "pagination", - ] - pruneopts = "UT" - revision = "aa00757ee3ab58e53520b6cb910ca0543116400a" - -[[projects]] - digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1" - name = "github.com/gorilla/context" - packages = ["."] - pruneopts = "UT" - revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" - version = "v1.1.1" - -[[projects]] - digest = "1:c661dee65a46d437daf269e5f5f462bd9df6d8e7c9750ad1655fb2cafdb177a6" - name = "github.com/gorilla/mux" - packages = ["."] - pruneopts = "UT" - revision = "e444e69cbd2e2e3e0749a2f3c717cec491552bbf" - -[[projects]] - branch = "master" - digest = "1:76ee51c3f468493aff39dbacc401e8831fbb765104cbf613b89bef01cf4bad70" - name = "golang.org/x/net" - packages = ["context"] - pruneopts = "UT" - revision = "03003ca0c849e57b6ea29a4bab8d3cb6e4d568fe" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "github.com/Sirupsen/logrus", - "github.com/docker/distribution/context", - "github.com/docker/distribution/registry/api/errcode", - "github.com/docker/distribution/registry/auth", - "github.com/docker/distribution/registry/auth/token", - "github.com/docker/libtrust", - "github.com/gophercloud/gophercloud", - "github.com/gophercloud/gophercloud/openstack", - "github.com/gorilla/mux", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/kubernetes/registry-token-server/src/Gopkg.toml b/kubernetes/registry-token-server/src/Gopkg.toml deleted file mode 100644 index 69a89e89e..000000000 --- a/kubernetes/registry-token-server/src/Gopkg.toml +++ /dev/null @@ -1,50 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - - -[[constraint]] - name = "github.com/Sirupsen/logrus" - revision = "55eb11d21d2a31a3cc93838241d04800f52e823d" - -[[constraint]] - name = "github.com/docker/distribution" - version = "2.6.2" - -[prune] - go-tests = true - unused-packages = true - -[[constraint]] - name = "github.com/docker/libtrust" - revision = "fa567046d9b14f6aa788882a950d69651d230b21" - -[[constraint]] - name = "github.com/gorilla/mux" - revision = "e444e69cbd2e2e3e0749a2f3c717cec491552bbf" - -[[constraint]] - name = "github.com/gophercloud/gophercloud" - revision = "aa00757ee3ab58e53520b6cb910ca0543116400a" diff --git a/kubernetes/registry-token-server/src/LICENSE b/kubernetes/registry-token-server/src/LICENSE deleted file mode 100644 index e06d20818..000000000 --- a/kubernetes/registry-token-server/src/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/kubernetes/registry-token-server/src/errors.go b/kubernetes/registry-token-server/src/errors.go deleted file mode 100644 index a69835e79..000000000 --- a/kubernetes/registry-token-server/src/errors.go +++ /dev/null @@ -1,43 +0,0 @@ -// Initial file was taken from https://github.com/docker/distribution 2018 Sept -// -// SPDX-License-Identifier: Apache-2.0 -// - -package main - -import ( - "net/http" - - "github.com/docker/distribution/registry/api/errcode" -) - -var ( - errGroup = "tokenserver" - - // ErrorBadTokenOption is returned when a token parameter is invalid - ErrorBadTokenOption = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "BAD_TOKEN_OPTION", - Message: "bad token option", - Description: `This error may be returned when a request for a - token contains an option which is not valid`, - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorMissingRequiredField is returned when a required form field is missing - ErrorMissingRequiredField = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "MISSING_REQUIRED_FIELD", - Message: "missing required field", - Description: `This error may be returned when a request for a - token does not contain a required form field`, - HTTPStatusCode: http.StatusBadRequest, - }) - - // ErrorUnsupportedValue is returned when a form field has an unsupported value - ErrorUnsupportedValue = errcode.Register(errGroup, errcode.ErrorDescriptor{ - Value: "UNSUPPORTED_VALUE", - Message: "unsupported value", - Description: `This error may be returned when a request for a - token contains a form field with an unsupported value`, - HTTPStatusCode: http.StatusBadRequest, - }) -) diff --git a/kubernetes/registry-token-server/src/keystone/access.go b/kubernetes/registry-token-server/src/keystone/access.go deleted file mode 100644 index f9d024441..000000000 --- a/kubernetes/registry-token-server/src/keystone/access.go +++ /dev/null @@ -1,96 +0,0 @@ -// Initial file was taken from https://github.com/docker/distribution 2018 Sept -// -// Copyright (c) 2018 Wind River Systems, Inc. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Package keystone provides a simple authentication scheme that checks for the -// user credential against keystone with configuration-determined endpoint -// -// This authentication method MUST be used under TLS, as simple token-replay attack is possible. -package keystone - -import ( - "fmt" - "net/http" - - "github.com/docker/distribution/context" - "github.com/docker/distribution/registry/auth" - "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/openstack" -) - -type accessController struct { - realm string - endpoint string -} - -var _ auth.AccessController = &accessController{} - -func newAccessController(options map[string]interface{}) (auth.AccessController, error) { - realm, present := options["realm"] - if _, ok := realm.(string); !present || !ok { - return nil, fmt.Errorf(`"realm" must be set for keystone access controller`) - } - - endpoint, present := options["endpoint"] - if _, ok := endpoint.(string); !present || !ok { - return nil, fmt.Errorf(`"endpoint" must be set for keystone access controller`) - } - - return &accessController{realm: realm.(string), endpoint: endpoint.(string)}, nil -} - -func (ac *accessController) Authorized(ctx context.Context, accessRecords ...auth.Access) (context.Context, error) { - req, err := context.GetRequest(ctx) - if err != nil { - return nil, err - } - - username, password, ok := req.BasicAuth() - if !ok { - return nil, &challenge{ - realm: ac.realm, - err: auth.ErrInvalidCredential, - } - } - - opts := gophercloud.AuthOptions{ - IdentityEndpoint: ac.endpoint, - Username: username, - Password: password, - DomainID: "default", - } - - if _, err := openstack.AuthenticatedClient(opts); err != nil { - context.GetLogger(ctx).Errorf("error authenticating user %q: %v", username, err) - return nil, &challenge{ - realm: ac.realm, - err: auth.ErrAuthenticationFailure, - } - } - - return auth.WithUser(ctx, auth.UserInfo{Name: username}), nil -} - -// challenge implements the auth.Challenge interface. -type challenge struct { - realm string - err error -} - -var _ auth.Challenge = challenge{} - -// SetHeaders sets the basic challenge header on the response. -func (ch challenge) SetHeaders(w http.ResponseWriter) { - w.Header().Set("WWW-Authenticate", fmt.Sprintf("Basic realm=%q", ch.realm)) -} - -func (ch challenge) Error() string { - return fmt.Sprintf("basic authentication challenge for realm %q: %s", ch.realm, ch.err) -} - -func init() { - auth.Register("keystone", auth.InitFunc(newAccessController)) -} - diff --git a/kubernetes/registry-token-server/src/main.go b/kubernetes/registry-token-server/src/main.go deleted file mode 100644 index fcf43dd7e..000000000 --- a/kubernetes/registry-token-server/src/main.go +++ /dev/null @@ -1,435 +0,0 @@ -// Initial file was taken from https://github.com/docker/distribution 2018 Sept -// -// Copyright (c) 2018 Wind River Systems, Inc. -// -// SPDX-License-Identifier: Apache-2.0 -// - -package main - -import ( - "encoding/json" - "flag" - "math/rand" - "net/http" - "strconv" - "strings" - "time" - - "github.com/Sirupsen/logrus" - "github.com/docker/distribution/context" - "github.com/docker/distribution/registry/api/errcode" - "github.com/docker/distribution/registry/auth" - _ "registry-token-server/keystone" - "github.com/docker/libtrust" - "github.com/gorilla/mux" -) - -var ( - enforceRepoClass bool -) - -func main() { - var ( - issuer = &TokenIssuer{} - pkFile string - addr string - debug bool - err error - - keystoneEndpoint string - realm string - - cert string - certKey string - ) - - flag.StringVar(&issuer.Issuer, "issuer", "distribution-token-server", "Issuer string for token") - flag.StringVar(&pkFile, "key", "", "Private key file") - flag.StringVar(&addr, "addr", "localhost:8080", "Address to listen on") - flag.BoolVar(&debug, "debug", false, "Debug mode") - - flag.StringVar(&keystoneEndpoint, "endpoint", "", "Passwd file") - flag.StringVar(&realm, "realm", "", "Authentication realm") - - flag.StringVar(&cert, "tlscert", "", "Certificate file for TLS") - flag.StringVar(&certKey, "tlskey", "", "Certificate key for TLS") - - flag.BoolVar(&enforceRepoClass, "enforce-class", false, "Enforce policy for single repository class") - - flag.Parse() - - if debug { - logrus.SetLevel(logrus.DebugLevel) - } - - if pkFile == "" { - issuer.SigningKey, err = libtrust.GenerateECP256PrivateKey() - if err != nil { - logrus.Fatalf("Error generating private key: %v", err) - } - logrus.Debugf("Using newly generated key with id %s", issuer.SigningKey.KeyID()) - } else { - issuer.SigningKey, err = libtrust.LoadKeyFile(pkFile) - if err != nil { - logrus.Fatalf("Error loading key file %s: %v", pkFile, err) - } - logrus.Debugf("Loaded private key with id %s", issuer.SigningKey.KeyID()) - } - - if realm == "" { - logrus.Fatalf("Must provide realm") - } - - ac, err := auth.GetAccessController("keystone", map[string]interface{}{ - "realm": realm, - "endpoint": keystoneEndpoint, - }) - if err != nil { - logrus.Fatalf("Error initializing access controller: %v", err) - } - - // TODO: Make configurable - issuer.Expiration = 15 * time.Minute - - ctx := context.Background() - - ts := &tokenServer{ - issuer: issuer, - accessController: ac, - refreshCache: map[string]refreshToken{}, - } - - router := mux.NewRouter() - router.Path("/token/").Methods("GET").Handler(handlerWithContext(ctx, ts.getToken)) - router.Path("/token/").Methods("POST").Handler(handlerWithContext(ctx, ts.postToken)) - - if cert == "" { - err = http.ListenAndServe(addr, router) - } else if certKey == "" { - logrus.Fatalf("Must provide certficate (-tlscert) and key (-tlskey)") - } else { - err = http.ListenAndServeTLS(addr, cert, certKey, router) - } - - if err != nil { - logrus.Infof("Error serving: %v", err) - } - -} - -// handlerWithContext wraps the given context-aware handler by setting up the -// request context from a base context. -func handlerWithContext(ctx context.Context, handler func(context.Context, http.ResponseWriter, *http.Request)) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := context.WithRequest(ctx, r) - logger := context.GetRequestLogger(ctx) - ctx = context.WithLogger(ctx, logger) - - handler(ctx, w, r) - }) -} - -func handleError(ctx context.Context, err error, w http.ResponseWriter) { - ctx, w = context.WithResponseWriter(ctx, w) - - if serveErr := errcode.ServeJSON(w, err); serveErr != nil { - context.GetResponseLogger(ctx).Errorf("error sending error response: %v", serveErr) - return - } - - context.GetResponseLogger(ctx).Info("application error") -} - -var refreshCharacters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - -const refreshTokenLength = 15 - -func newRefreshToken() string { - s := make([]rune, refreshTokenLength) - for i := range s { - s[i] = refreshCharacters[rand.Intn(len(refreshCharacters))] - } - return string(s) -} - -type refreshToken struct { - subject string - service string -} - -type tokenServer struct { - issuer *TokenIssuer - accessController auth.AccessController - refreshCache map[string]refreshToken -} - -type tokenResponse struct { - Token string `json:"access_token"` - RefreshToken string `json:"refresh_token,omitempty"` - ExpiresIn int `json:"expires_in,omitempty"` -} - -var repositoryClassCache = map[string]string{} - -func filterAccessList(ctx context.Context, scope string, requestedAccessList []auth.Access) []auth.Access { - if !strings.HasSuffix(scope, "/") { - scope = scope + "/" - } - grantedAccessList := make([]auth.Access, 0, len(requestedAccessList)) - for _, access := range requestedAccessList { - if access.Type == "repository" { - // filter access to repos if the user is not "admin" - // need to have a "/" at the end because it adds one at the beginning of the fcn - // probably to prevent people making accounts like "adminnot" to steal admin powers - if !strings.HasPrefix(access.Name, scope) && scope != "admin/" { - context.GetLogger(ctx).Debugf("Resource scope not allowed: %s", access.Name) - continue - } - if enforceRepoClass { - if class, ok := repositoryClassCache[access.Name]; ok { - if class != access.Class { - context.GetLogger(ctx).Debugf("Different repository class: %q, previously %q", access.Class, class) - continue - } - } else if strings.EqualFold(access.Action, "push") { - repositoryClassCache[access.Name] = access.Class - } - } - } else if access.Type == "registry" { - if access.Name != "catalog" { - context.GetLogger(ctx).Debugf("Unknown registry resource: %s", access.Name) - continue - } - // TODO: Limit some actions to "admin" users - } else { - context.GetLogger(ctx).Debugf("Skipping unsupported resource type: %s", access.Type) - continue - } - grantedAccessList = append(grantedAccessList, access) - } - return grantedAccessList -} - -type acctSubject struct{} - -func (acctSubject) String() string { return "acctSubject" } - -type requestedAccess struct{} - -func (requestedAccess) String() string { return "requestedAccess" } - -type grantedAccess struct{} - -func (grantedAccess) String() string { return "grantedAccess" } - -// getToken handles authenticating the request and authorizing access to the -// requested scopes. -func (ts *tokenServer) getToken(ctx context.Context, w http.ResponseWriter, r *http.Request) { - context.GetLogger(ctx).Info("getToken") - - params := r.URL.Query() - service := params.Get("service") - scopeSpecifiers := params["scope"] - var offline bool - if offlineStr := params.Get("offline_token"); offlineStr != "" { - var err error - offline, err = strconv.ParseBool(offlineStr) - if err != nil { - handleError(ctx, ErrorBadTokenOption.WithDetail(err), w) - return - } - } - - requestedAccessList := ResolveScopeSpecifiers(ctx, scopeSpecifiers) - - authorizedCtx, err := ts.accessController.Authorized(ctx, requestedAccessList...) - if err != nil { - challenge, ok := err.(auth.Challenge) - if !ok { - handleError(ctx, err, w) - return - } - - // Get response context. - ctx, w = context.WithResponseWriter(ctx, w) - - challenge.SetHeaders(w) - handleError(ctx, errcode.ErrorCodeUnauthorized.WithDetail(challenge.Error()), w) - - context.GetResponseLogger(ctx).Info("get token authentication challenge") - - return - } - ctx = authorizedCtx - - username := context.GetStringValue(ctx, "auth.user.name") - - ctx = context.WithValue(ctx, acctSubject{}, username) - ctx = context.WithLogger(ctx, context.GetLogger(ctx, acctSubject{})) - - context.GetLogger(ctx).Info("authenticated client") - - ctx = context.WithValue(ctx, requestedAccess{}, requestedAccessList) - ctx = context.WithLogger(ctx, context.GetLogger(ctx, requestedAccess{})) - - grantedAccessList := filterAccessList(ctx, username, requestedAccessList) - ctx = context.WithValue(ctx, grantedAccess{}, grantedAccessList) - ctx = context.WithLogger(ctx, context.GetLogger(ctx, grantedAccess{})) - - token, err := ts.issuer.CreateJWT(username, service, grantedAccessList) - if err != nil { - handleError(ctx, err, w) - return - } - - context.GetLogger(ctx).Info("authorized client") - - response := tokenResponse{ - Token: token, - ExpiresIn: int(ts.issuer.Expiration.Seconds()), - } - - if offline { - response.RefreshToken = newRefreshToken() - ts.refreshCache[response.RefreshToken] = refreshToken{ - subject: username, - service: service, - } - } - - ctx, w = context.WithResponseWriter(ctx, w) - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(response) - - context.GetResponseLogger(ctx).Info("get token complete") -} - -type postTokenResponse struct { - Token string `json:"access_token"` - Scope string `json:"scope,omitempty"` - ExpiresIn int `json:"expires_in,omitempty"` - IssuedAt string `json:"issued_at,omitempty"` - RefreshToken string `json:"refresh_token,omitempty"` -} - -// postToken handles authenticating the request and authorizing access to the -// requested scopes. -func (ts *tokenServer) postToken(ctx context.Context, w http.ResponseWriter, r *http.Request) { - grantType := r.PostFormValue("grant_type") - if grantType == "" { - handleError(ctx, ErrorMissingRequiredField.WithDetail("missing grant_type value"), w) - return - } - - service := r.PostFormValue("service") - if service == "" { - handleError(ctx, ErrorMissingRequiredField.WithDetail("missing service value"), w) - return - } - - clientID := r.PostFormValue("client_id") - if clientID == "" { - handleError(ctx, ErrorMissingRequiredField.WithDetail("missing client_id value"), w) - return - } - - var offline bool - switch r.PostFormValue("access_type") { - case "", "online": - case "offline": - offline = true - default: - handleError(ctx, ErrorUnsupportedValue.WithDetail("unknown access_type value"), w) - return - } - - requestedAccessList := ResolveScopeList(ctx, r.PostFormValue("scope")) - - var subject string - var rToken string - switch grantType { - case "refresh_token": - rToken = r.PostFormValue("refresh_token") - if rToken == "" { - handleError(ctx, ErrorUnsupportedValue.WithDetail("missing refresh_token value"), w) - return - } - rt, ok := ts.refreshCache[rToken] - if !ok || rt.service != service { - handleError(ctx, errcode.ErrorCodeUnauthorized.WithDetail("invalid refresh token"), w) - return - } - subject = rt.subject - case "password": - ca, ok := ts.accessController.(auth.CredentialAuthenticator) - if !ok { - handleError(ctx, ErrorUnsupportedValue.WithDetail("password grant type not supported"), w) - return - } - subject = r.PostFormValue("username") - if subject == "" { - handleError(ctx, ErrorUnsupportedValue.WithDetail("missing username value"), w) - return - } - password := r.PostFormValue("password") - if password == "" { - handleError(ctx, ErrorUnsupportedValue.WithDetail("missing password value"), w) - return - } - if err := ca.AuthenticateUser(subject, password); err != nil { - handleError(ctx, errcode.ErrorCodeUnauthorized.WithDetail("invalid credentials"), w) - return - } - default: - handleError(ctx, ErrorUnsupportedValue.WithDetail("unknown grant_type value"), w) - return - } - - ctx = context.WithValue(ctx, acctSubject{}, subject) - ctx = context.WithLogger(ctx, context.GetLogger(ctx, acctSubject{})) - - context.GetLogger(ctx).Info("authenticated client") - - ctx = context.WithValue(ctx, requestedAccess{}, requestedAccessList) - ctx = context.WithLogger(ctx, context.GetLogger(ctx, requestedAccess{})) - - grantedAccessList := filterAccessList(ctx, subject, requestedAccessList) - ctx = context.WithValue(ctx, grantedAccess{}, grantedAccessList) - ctx = context.WithLogger(ctx, context.GetLogger(ctx, grantedAccess{})) - - token, err := ts.issuer.CreateJWT(subject, service, grantedAccessList) - if err != nil { - handleError(ctx, err, w) - return - } - - context.GetLogger(ctx).Info("authorized client") - - response := postTokenResponse{ - Token: token, - ExpiresIn: int(ts.issuer.Expiration.Seconds()), - IssuedAt: time.Now().UTC().Format(time.RFC3339), - Scope: ToScopeList(grantedAccessList), - } - - if offline { - rToken = newRefreshToken() - ts.refreshCache[rToken] = refreshToken{ - subject: subject, - service: service, - } - } - - if rToken != "" { - response.RefreshToken = rToken - } - - ctx, w = context.WithResponseWriter(ctx, w) - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(response) - - context.GetResponseLogger(ctx).Info("post token complete") -} diff --git a/kubernetes/registry-token-server/src/token.go b/kubernetes/registry-token-server/src/token.go deleted file mode 100644 index 2a03b224e..000000000 --- a/kubernetes/registry-token-server/src/token.go +++ /dev/null @@ -1,224 +0,0 @@ -// Initial file was taken from https://github.com/docker/distribution 2018 Sept -// -// SPDX-License-Identifier: Apache-2.0 -// - -package main - -import ( - "crypto" - "crypto/rand" - "encoding/base64" - "encoding/json" - "fmt" - "io" - "regexp" - "strings" - "time" - - "github.com/docker/distribution/context" - "github.com/docker/distribution/registry/auth" - "github.com/docker/distribution/registry/auth/token" - "github.com/docker/libtrust" -) - -// ResolveScopeSpecifiers converts a list of scope specifiers from a token -// request's `scope` query parameters into a list of standard access objects. -func ResolveScopeSpecifiers(ctx context.Context, scopeSpecs []string) []auth.Access { - requestedAccessSet := make(map[auth.Access]struct{}, 2*len(scopeSpecs)) - - for _, scopeSpecifier := range scopeSpecs { - // There should be 3 parts, separated by a `:` character. - parts := strings.SplitN(scopeSpecifier, ":", 3) - - if len(parts) != 3 { - context.GetLogger(ctx).Infof("ignoring unsupported scope format %s", scopeSpecifier) - continue - } - - resourceType, resourceName, actions := parts[0], parts[1], parts[2] - - resourceType, resourceClass := splitResourceClass(resourceType) - if resourceType == "" { - continue - } - - // Actions should be a comma-separated list of actions. - for _, action := range strings.Split(actions, ",") { - requestedAccess := auth.Access{ - Resource: auth.Resource{ - Type: resourceType, - Class: resourceClass, - Name: resourceName, - }, - Action: action, - } - - // Add this access to the requested access set. - requestedAccessSet[requestedAccess] = struct{}{} - } - } - - requestedAccessList := make([]auth.Access, 0, len(requestedAccessSet)) - for requestedAccess := range requestedAccessSet { - requestedAccessList = append(requestedAccessList, requestedAccess) - } - - return requestedAccessList -} - -var typeRegexp = regexp.MustCompile(`^([a-z0-9]+)(\([a-z0-9]+\))?$`) - -func splitResourceClass(t string) (string, string) { - matches := typeRegexp.FindStringSubmatch(t) - if len(matches) < 2 { - return "", "" - } - if len(matches) == 2 || len(matches[2]) < 2 { - return matches[1], "" - } - return matches[1], matches[2][1 : len(matches[2])-1] -} - -// ResolveScopeList converts a scope list from a token request's -// `scope` parameter into a list of standard access objects. -func ResolveScopeList(ctx context.Context, scopeList string) []auth.Access { - scopes := strings.Split(scopeList, " ") - return ResolveScopeSpecifiers(ctx, scopes) -} - -func scopeString(a auth.Access) string { - if a.Class != "" { - return fmt.Sprintf("%s(%s):%s:%s", a.Type, a.Class, a.Name, a.Action) - } - return fmt.Sprintf("%s:%s:%s", a.Type, a.Name, a.Action) -} - -// ToScopeList converts a list of access to a -// scope list string -func ToScopeList(access []auth.Access) string { - var s []string - for _, a := range access { - s = append(s, scopeString(a)) - } - return strings.Join(s, ",") -} - -// TokenIssuer represents an issuer capable of generating JWT tokens -type TokenIssuer struct { - Issuer string - SigningKey libtrust.PrivateKey - Expiration time.Duration -} - -// CreateJWT creates and signs a JSON Web Token for the given subject and -// audience with the granted access. -func (issuer *TokenIssuer) CreateJWT(subject string, audience string, grantedAccessList []auth.Access) (string, error) { - // Make a set of access entries to put in the token's claimset. - resourceActionSets := make(map[auth.Resource]map[string]struct{}, len(grantedAccessList)) - for _, access := range grantedAccessList { - actionSet, exists := resourceActionSets[access.Resource] - if !exists { - actionSet = map[string]struct{}{} - resourceActionSets[access.Resource] = actionSet - } - actionSet[access.Action] = struct{}{} - } - - accessEntries := make([]*token.ResourceActions, 0, len(resourceActionSets)) - for resource, actionSet := range resourceActionSets { - actions := make([]string, 0, len(actionSet)) - for action := range actionSet { - actions = append(actions, action) - } - - accessEntries = append(accessEntries, &token.ResourceActions{ - Type: resource.Type, - Class: resource.Class, - Name: resource.Name, - Actions: actions, - }) - } - - randomBytes := make([]byte, 15) - _, err := io.ReadFull(rand.Reader, randomBytes) - if err != nil { - return "", err - } - randomID := base64.URLEncoding.EncodeToString(randomBytes) - - now := time.Now() - - signingHash := crypto.SHA256 - var alg string - switch issuer.SigningKey.KeyType() { - case "RSA": - alg = "RS256" - case "EC": - alg = "ES256" - default: - panic(fmt.Errorf("unsupported signing key type %q", issuer.SigningKey.KeyType())) - } - - joseHeader := token.Header{ - Type: "JWT", - SigningAlg: alg, - } - - if x5c := issuer.SigningKey.GetExtendedField("x5c"); x5c != nil { - joseHeader.X5c = x5c.([]string) - } else { - var jwkMessage json.RawMessage - jwkMessage, err = issuer.SigningKey.PublicKey().MarshalJSON() - if err != nil { - return "", err - } - joseHeader.RawJWK = &jwkMessage - } - - exp := issuer.Expiration - if exp == 0 { - exp = 5 * time.Minute - } - - claimSet := token.ClaimSet{ - Issuer: issuer.Issuer, - Subject: subject, - Audience: audience, - Expiration: now.Add(exp).Unix(), - NotBefore: now.Unix(), - IssuedAt: now.Unix(), - JWTID: randomID, - - Access: accessEntries, - } - - var ( - joseHeaderBytes []byte - claimSetBytes []byte - ) - - if joseHeaderBytes, err = json.Marshal(joseHeader); err != nil { - return "", fmt.Errorf("unable to encode jose header: %s", err) - } - if claimSetBytes, err = json.Marshal(claimSet); err != nil { - return "", fmt.Errorf("unable to encode claim set: %s", err) - } - - encodedJoseHeader := joseBase64Encode(joseHeaderBytes) - encodedClaimSet := joseBase64Encode(claimSetBytes) - encodingToSign := fmt.Sprintf("%s.%s", encodedJoseHeader, encodedClaimSet) - - var signatureBytes []byte - if signatureBytes, _, err = issuer.SigningKey.Sign(strings.NewReader(encodingToSign), signingHash); err != nil { - return "", fmt.Errorf("unable to sign jwt payload: %s", err) - } - - signature := joseBase64Encode(signatureBytes) - - return fmt.Sprintf("%s.%s", encodingToSign, signature), nil -} - -func joseBase64Encode(data []byte) string { - return strings.TrimRight(base64.URLEncoding.EncodeToString(data), "=") -}