Merge pull request #10706 from ninjadq/enable_tls_on_all_components

Enable tls on all components
This commit is contained in:
Qian Deng 2020-03-18 21:25:40 +08:00 committed by GitHub
commit cf90ec27f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
76 changed files with 1234 additions and 395 deletions

View File

@ -5,7 +5,6 @@ env:
POSTGRESQL_USR: postgres
POSTGRESQL_PWD: root123
POSTGRESQL_DATABASE: registry
ADMINSERVER_URL: http://127.0.0.1:8888
DOCKER_COMPOSE_VERSION: 1.23.0
HARBOR_ADMIN: admin
HARBOR_ADMIN_PASSWD: Harbor12345

View File

@ -85,6 +85,7 @@ NPM_REGISTRY=https://registry.npmjs.org
# enable/disable chart repo supporting
CHARTFLAG=false
BUILDTARGET=build
GEN_TLS=
# version prepare
# for docker image tag
@ -349,10 +350,16 @@ compile: check_environment versions_prepare compile_core compile_jobservice comp
update_prepare_version:
@echo "substitute the prepare version tag in prepare file..."
@$(SEDCMDI) -e 's/goharbor\/prepare:.*[[:space:]]\+/goharbor\/prepare:$(VERSIONTAG) /' $(MAKEPATH)/prepare ;
@$(SEDCMDI) -e 's/goharbor\/prepare:.*[[:space:]]\+/goharbor\/prepare:$(VERSIONTAG) prepare /' $(MAKEPATH)/prepare ;
gen_tls:
@$(DOCKERCMD) run --rm -v /:/hostfs:z goharbor/prepare:$(VERSIONTAG) gencert -p /etc/harbor/tls/internal
prepare: update_prepare_version
@echo "preparing..."
@if [ -n "$(GEN_TLS)" ] ; then \
$(DOCKERCMD) run --rm -v /:/hostfs:z goharbor/prepare:$(VERSIONTAG) gencert -p /etc/harbor/tls/internal; \
fi
@$(MAKEPATH)/$(PREPARECMD) $(PREPARECMD_PARA)
build:

View File

@ -17,6 +17,15 @@ https:
certificate: /your/certificate/path
private_key: /your/private/key/path
# # Uncomment following will enable tls communication between all harbor components
# internal_tls:
# # set enabled to true means internal tls is enabled
# enabled: true
# # verify_client_cert used to decide whether verify client certificate
# verify_client_cert: false
# # put your cert and key files on dir
# dir: /etc/harbor/tls/internal
# Uncomment external_url if you want to enable external proxy
# And when it enabled the hostname will no longer used
# external_url: https://reg.mydomain.com:8433

View File

@ -1,10 +1,14 @@
ARG harbor_base_image_version
FROM goharbor/harbor-clair-adapter-base:${harbor_base_image_version}
COPY ./make/photon/common/install_cert.sh /home/clair-adapter
COPY ./make/photon/clair-adapter/entrypoint.sh /home/clair-adapter
COPY ./make/photon/clair-adapter/binary/harbor-scanner-clair /clair-adapter/clair-adapter
RUN chown -R 10000:10000 /clair-adapter \
&& chmod u+x /clair-adapter/clair-adapter
RUN chown -R clair-adapter:clair-adapter /etc/pki/tls/certs \
&& chown -R clair-adapter:clair-adapter /clair-adapter && chmod u+x /clair-adapter/clair-adapter \
&& chown clair-adapter:clair-adapter /home/clair-adapter/entrypoint.sh && chmod u+x /home/clair-adapter/entrypoint.sh \
&& chown clair-adapter:clair-adapter /home/clair-adapter/install_cert.sh && chmod u+x /home/clair-adapter/install_cert.sh
EXPOSE 8080
@ -12,4 +16,4 @@ HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD curl -sS 127.0.0.1:8080
USER clair-adapter
ENTRYPOINT ["/clair-adapter/clair-adapter"]
ENTRYPOINT ["/home/clair-adapter/entrypoint.sh"]

View File

@ -0,0 +1,7 @@
#!/bin/sh
set -e
/home/clair-adapter/install_cert.sh
/clair-adapter/clair-adapter

View File

@ -10,10 +10,10 @@ VOLUME /config
EXPOSE 6060 6061
RUN chown -R clair:clair /etc/pki/tls/certs \
&& chown -R clair:clair /home/clair \
RUN chown -R clair:clair /etc/pki/tls/certs && chown -R clair:clair /home/clair \
&& chmod u+x /home/clair/clair \
&& chmod u+x /home/clair/docker-entrypoint.sh \
&& chmod u+x /home/clair/install_cert.sh \
&& chmod +x /home/clair/dumb-init
HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD curl -sS 127.0.0.1:6061/health || exit 1

View File

@ -2,12 +2,18 @@ ARG harbor_base_image_version
FROM goharbor/harbor-core-base:${harbor_base_image_version}
HEALTHCHECK CMD curl --fail -s http://127.0.0.1:8080/api/v2.0/ping || exit 1
COPY ./make/photon/common/install_cert.sh /harbor/
COPY ./make/photon/core/entrypoint.sh /harbor/
COPY ./make/photon/core/harbor_core /harbor/
COPY ./src/core/views /harbor/views
COPY ./make/migrations /harbor/migrations
RUN chmod u+x /harbor/harbor_core
RUN chown -R harbor:harbor /etc/pki/tls/certs \
&& chown harbor:harbor /harbor/entrypoint.sh && chmod u+x /harbor/entrypoint.sh \
&& chown harbor:harbor /harbor/install_cert.sh && chmod u+x /harbor/install_cert.sh \
&& chown harbor:harbor /harbor/harbor_core && chmod u+x /harbor/harbor_core
WORKDIR /harbor/
USER harbor
ENTRYPOINT ["/harbor/harbor_core"]
ENTRYPOINT ["/harbor/entrypoint.sh"]
COPY make/photon/prepare/versions /harbor/

View File

@ -2,5 +2,5 @@ FROM photon:2.0
RUN tdnf install sudo tzdata -y >> /dev/null \
&& tdnf clean all \
&& groupadd -r -g 10000 harbor && useradd --no-log-init -r -g 10000 -u 10000 harbor \
&& groupadd -r -g 10000 harbor && useradd --no-log-init -r -m -g 10000 -u 10000 harbor \
&& mkdir /harbor/

View File

@ -0,0 +1,7 @@
#!/bin/sh
set -e
/harbor/install_cert.sh
/harbor/harbor_core

View File

@ -1,9 +1,15 @@
ARG harbor_base_image_version
FROM goharbor/harbor-jobservice-base:${harbor_base_image_version}
COPY ./make/photon/common/install_cert.sh /harbor/
COPY ./make/photon/jobservice/entrypoint.sh /harbor/
COPY ./make/photon/jobservice/harbor_jobservice /harbor/
RUN chmod u+x /harbor/harbor_jobservice
RUN chown -R harbor:harbor /etc/pki/tls/certs \
&& chown harbor:harbor /harbor/entrypoint.sh && chmod u+x /harbor/entrypoint.sh \
&& chown harbor:harbor /harbor/install_cert.sh && chmod u+x /harbor/install_cert.sh \
&& chown harbor:harbor /harbor/harbor_jobservice && chmod u+x /harbor/harbor_jobservice
WORKDIR /harbor/
@ -13,4 +19,4 @@ VOLUME ["/var/log/jobs/"]
HEALTHCHECK CMD curl --fail -s http://127.0.0.1:8080/api/v1/stats || exit 1
ENTRYPOINT ["/harbor/harbor_jobservice", "-c", "/etc/jobservice/config.yml"]
ENTRYPOINT ["/harbor/entrypoint.sh"]

View File

@ -2,4 +2,4 @@ FROM photon:2.0
RUN tdnf install sudo tzdata -y >> /dev/null \
&& tdnf clean all \
&& groupadd -r -g 10000 harbor && useradd --no-log-init -r -g 10000 -u 10000 harbor
&& groupadd -r -g 10000 harbor && useradd --no-log-init -r -m -g 10000 -u 10000 harbor

View File

@ -0,0 +1,7 @@
#!/bin/sh
set -e
/harbor/install_cert.sh
/harbor/harbor_jobservice -c /etc/jobservice/config.yml

View File

@ -12,4 +12,4 @@ click = "*"
pylint = "*"
[requires]
python_version = "3.6"
python_version = "3.7.5"

View File

@ -1,11 +1,11 @@
{
"_meta": {
"hash": {
"sha256": "a3c7e13ece64f4447d0bd3648257ca4117192e5d52ff7cdd4b4c2d3109ae6500"
"sha256": "fc86f400c4b9ebc8d4caf833b1e8d8c8962b7f4920b19632e9e4f4e8738ce7e2"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.6"
"python_version": "3.7.5"
},
"sources": [
{
@ -26,11 +26,11 @@
},
"jinja2": {
"hashes": [
"sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
"sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
"sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f",
"sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"
],
"index": "pypi",
"version": "==2.10.1"
"version": "==2.10.3"
},
"markupsafe": {
"hashes": [
@ -76,51 +76,43 @@
"develop": {
"astroid": {
"hashes": [
"sha256:6560e1e1749f68c64a4b5dee4e091fce798d2f0d84ebe638cf0e0585a343acf4",
"sha256:b65db1bbaac9f9f4d190199bb8680af6f6f84fd3769a5ea883df8a91fe68b4c4"
"sha256:71ea07f44df9568a75d0f354c49143a4575d90645e9fead6dfb52c26a85ed13a",
"sha256:840947ebfa8b58f318d42301cf8c0a20fd794a33b61cc4638e28e9e61ba32f42"
],
"version": "==2.2.5"
"version": "==2.3.3"
},
"isort": {
"hashes": [
"sha256:01cb7e1ca5e6c5b3f235f0385057f70558b70d2f00320208825fa62887292f43",
"sha256:268067462aed7eb2a1e237fcb287852f22077de3fb07964e87e00f829eea2d1a"
"sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1",
"sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"
],
"version": "==4.3.17"
"version": "==4.3.21"
},
"lazy-object-proxy": {
"hashes": [
"sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33",
"sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39",
"sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019",
"sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088",
"sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b",
"sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e",
"sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6",
"sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b",
"sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5",
"sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff",
"sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd",
"sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7",
"sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff",
"sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d",
"sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2",
"sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35",
"sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4",
"sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514",
"sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252",
"sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109",
"sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f",
"sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c",
"sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92",
"sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577",
"sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d",
"sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d",
"sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f",
"sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a",
"sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b"
"sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d",
"sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449",
"sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08",
"sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a",
"sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50",
"sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd",
"sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239",
"sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb",
"sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea",
"sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e",
"sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156",
"sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142",
"sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442",
"sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62",
"sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db",
"sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531",
"sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383",
"sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a",
"sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357",
"sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4",
"sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"
],
"version": "==1.3.1"
"version": "==1.4.3"
},
"mccabe": {
"hashes": [
@ -131,50 +123,50 @@
},
"pylint": {
"hashes": [
"sha256:5d77031694a5fb97ea95e828c8d10fc770a1df6eb3906067aaed42201a8a6a09",
"sha256:723e3db49555abaf9bf79dc474c6b9e2935ad82230b10c1138a71ea41ac0fff1"
"sha256:3db5468ad013380e987410a8d6956226963aed94ecb5f9d3a28acca6d9ac36cd",
"sha256:886e6afc935ea2590b462664b161ca9a5e40168ea99e5300935f6591ad467df4"
],
"index": "pypi",
"version": "==2.3.1"
"version": "==2.4.4"
},
"six": {
"hashes": [
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
"sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd",
"sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"
],
"version": "==1.12.0"
"version": "==1.13.0"
},
"typed-ast": {
"hashes": [
"sha256:04894d268ba6eab7e093d43107869ad49e7b5ef40d1a94243ea49b352061b200",
"sha256:16616ece19daddc586e499a3d2f560302c11f122b9c692bc216e821ae32aa0d0",
"sha256:252fdae740964b2d3cdfb3f84dcb4d6247a48a6abe2579e8029ab3be3cdc026c",
"sha256:2af80a373af123d0b9f44941a46df67ef0ff7a60f95872412a145f4500a7fc99",
"sha256:2c88d0a913229a06282b285f42a31e063c3bf9071ff65c5ea4c12acb6977c6a7",
"sha256:2ea99c029ebd4b5a308d915cc7fb95b8e1201d60b065450d5d26deb65d3f2bc1",
"sha256:3d2e3ab175fc097d2a51c7a0d3fda442f35ebcc93bb1d7bd9b95ad893e44c04d",
"sha256:4766dd695548a15ee766927bf883fb90c6ac8321be5a60c141f18628fb7f8da8",
"sha256:56b6978798502ef66625a2e0f80cf923da64e328da8bbe16c1ff928c70c873de",
"sha256:5cddb6f8bce14325b2863f9d5ac5c51e07b71b462361fd815d1d7706d3a9d682",
"sha256:644ee788222d81555af543b70a1098f2025db38eaa99226f3a75a6854924d4db",
"sha256:64cf762049fc4775efe6b27161467e76d0ba145862802a65eefc8879086fc6f8",
"sha256:68c362848d9fb71d3c3e5f43c09974a0ae319144634e7a47db62f0f2a54a7fa7",
"sha256:6c1f3c6f6635e611d58e467bf4371883568f0de9ccc4606f17048142dec14a1f",
"sha256:b213d4a02eec4ddf622f4d2fbc539f062af3788d1f332f028a2e19c42da53f15",
"sha256:bb27d4e7805a7de0e35bd0cb1411bc85f807968b2b0539597a49a23b00a622ae",
"sha256:c9d414512eaa417aadae7758bc118868cd2396b0e6138c1dd4fda96679c079d3",
"sha256:f0937165d1e25477b01081c4763d2d9cdc3b18af69cb259dd4f640c9b900fe5e",
"sha256:fb96a6e2c11059ecf84e6741a319f93f683e440e341d4489c9b161eca251cf2a",
"sha256:fc71d2d6ae56a091a8d94f33ec9d0f2001d1cb1db423d8b4355debfe9ce689b7"
"sha256:1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161",
"sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e",
"sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e",
"sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0",
"sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c",
"sha256:48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47",
"sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631",
"sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4",
"sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34",
"sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b",
"sha256:7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2",
"sha256:838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e",
"sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a",
"sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233",
"sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1",
"sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36",
"sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d",
"sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a",
"sha256:fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66",
"sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12"
],
"markers": "implementation_name == 'cpython'",
"version": "==1.3.4"
"markers": "implementation_name == 'cpython' and python_version < '3.8'",
"version": "==1.4.0"
},
"wrapt": {
"hashes": [
"sha256:4aea003270831cceb8a90ff27c4031da6ead7ec1886023b80ce0dfe0adf61533"
"sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1"
],
"version": "==1.11.1"
"version": "==1.11.2"
}
}
}

View File

View File

@ -0,0 +1,29 @@
import os
import sys
import click
import pathlib
from subprocess import check_call, PIPE, STDOUT
from utils.cert import openssl_installed
from utils.misc import get_realpath
gen_tls_script = pathlib.Path(__file__).parent.parent.joinpath('scripts/gencert.sh').absolute()
@click.command()
@click.option('-p', '--path', default='/etc/harbor/tls/internal')
@click.option('-d', '--days', default='365')
def gencert(path, days):
path = get_realpath(path)
click.echo('Check openssl ...')
if not openssl_installed():
raise(Exception('openssl not installed'))
click.echo("start generate internal tls certs")
if not os.path.exists(path):
click.echo('path {} not exist, create it...'.format(path))
os.makedirs(path, exist_ok=True)
shell_stat = check_call([gen_tls_script, days], stdout=PIPE, stderr=STDOUT, cwd=path)
if shell_stat != 0:
click.echo('Can not generate internal tls certs')
sys.exit(-1)

View File

@ -0,0 +1,78 @@
# pylint: disable=no-value-for-parameter
import sys
import logging
import click
from utils.misc import delfile
from utils.configs import validate, parse_yaml_config
from utils.cert import prepare_registry_ca, SSL_CERT_KEY_PATH, SSL_CERT_PATH, get_secret_key
from utils.db import prepare_db
from utils.jobservice import prepare_job_service
from utils.registry import prepare_registry
from utils.registry_ctl import prepare_registry_ctl
from utils.core import prepare_core
from utils.notary import prepare_notary
from utils.log import prepare_log_configs
from utils.clair import prepare_clair
from utils.clair_adapter import prepare_clair_adapter
from utils.chart import prepare_chartmuseum
from utils.docker_compose import prepare_docker_compose
from utils.nginx import prepare_nginx, nginx_confd_dir
from utils.redis import prepare_redis
from utils.internal_tls import prepare_tls
from utils.trivy_adapter import prepare_trivy_adapter
from g import (config_dir, input_config_path, private_key_pem_path, root_crt_path, secret_key_dir,
old_private_key_pem_path, old_crt_path)
@click.command()
@click.option('--conf', default=input_config_path, help="the path of Harbor configuration file")
@click.option('--with-notary', is_flag=True, help="the Harbor instance is to be deployed with notary")
@click.option('--with-clair', is_flag=True, help="the Harbor instance is to be deployed with clair")
@click.option('--with-trivy', is_flag=True, help="the Harbor instance is to be deployed with Trivy")
@click.option('--with-chartmuseum', is_flag=True, help="the Harbor instance is to be deployed with chart repository supporting")
def prepare(conf, with_notary, with_clair, with_trivy, with_chartmuseum):
delfile(config_dir)
config_dict = parse_yaml_config(conf, with_notary=with_notary, with_clair=with_clair, with_trivy=with_trivy, with_chartmuseum=with_chartmuseum)
try:
validate(config_dict, notary_mode=with_notary)
except Exception as e:
click.echo('Error happened in config validation...')
logging.error(e)
sys.exit(-1)
prepare_log_configs(config_dict)
prepare_nginx(config_dict)
prepare_core(config_dict, with_notary=with_notary, with_clair=with_clair, with_trivy=with_trivy, with_chartmuseum=with_chartmuseum)
prepare_registry(config_dict)
prepare_registry_ctl(config_dict)
prepare_db(config_dict)
prepare_job_service(config_dict)
prepare_redis(config_dict)
prepare_tls(config_dict)
get_secret_key(secret_key_dir)
# If Customized cert enabled
prepare_registry_ca(
private_key_pem_path=private_key_pem_path,
root_crt_path=root_crt_path,
old_private_key_pem_path=old_private_key_pem_path,
old_crt_path=old_crt_path)
if with_notary:
prepare_notary(config_dict, nginx_confd_dir, SSL_CERT_PATH, SSL_CERT_KEY_PATH)
if with_clair:
prepare_clair(config_dict)
prepare_clair_adapter(config_dict)
if with_trivy:
prepare_trivy_adapter(config_dict)
if with_chartmuseum:
prepare_chartmuseum(config_dict)
prepare_docker_compose(config_dict, with_clair, with_trivy, with_notary, with_chartmuseum)

View File

@ -12,27 +12,33 @@ REDIS_UID = 999
REDIS_GID = 999
## Global variable
host_root_dir = '/hostfs'
templates_dir = "/usr/src/app/templates"
host_root_dir = Path('/hostfs')
base_dir = '/harbor_make'
templates_dir = "/usr/src/app/templates"
config_dir = '/config'
data_dir = '/data'
secret_dir = '/secret'
secret_key_dir = '/secret/keys'
config_dir = Path('/config')
data_dir = Path('/data')
secret_dir = data_dir.joinpath('secret')
secret_key_dir = secret_dir.joinpath('keys')
trust_ca_dir = secret_dir.joinpath('keys', 'trust_ca')
internal_tls_dir = secret_dir.joinpath('tls')
storage_ca_bundle_filename = 'storage_ca_bundle.crt'
old_private_key_pem_path = Path('/config/core/private_key.pem')
old_crt_path = Path('/config/registry/root.crt')
private_key_pem_path = Path('/secret/core/private_key.pem')
root_crt_path = Path('/secret/registry/root.crt')
private_key_pem_path = secret_dir.joinpath('core', 'private_key.pem')
root_crt_path = secret_dir.joinpath('registry', 'root.crt')
config_file_path = '/compose_location/harbor.yml'
input_config_path = '/input/harbor.yml'
versions_file_path = Path('/usr/src/app/versions')
cert_dir = os.path.join(config_dir, "nginx", "cert")
core_cert_dir = os.path.join(config_dir, "core", "certificates")
cert_dir = config_dir.joinpath("nginx", "cert")
core_cert_dir = config_dir.joinpath("core", "certificates")
INTERNAL_NO_PROXY_DN = {
'127.0.0.1',

View File

@ -1,77 +1,13 @@
# pylint: disable=no-value-for-parameter
import sys
import logging
from commands.prepare import prepare
from commands.gencerts import gencert
import click
from utils.misc import delfile
from utils.configs import validate, parse_yaml_config
from utils.cert import prepare_ca, SSL_CERT_KEY_PATH, SSL_CERT_PATH, get_secret_key
from utils.db import prepare_db
from utils.jobservice import prepare_job_service
from utils.registry import prepare_registry
from utils.registry_ctl import prepare_registry_ctl
from utils.core import prepare_core
from utils.notary import prepare_notary
from utils.log import prepare_log_configs
from utils.clair import prepare_clair
from utils.clair_adapter import prepare_clair_adapter
from utils.trivy_adapter import prepare_trivy_adapter
from utils.chart import prepare_chartmuseum
from utils.docker_compose import prepare_docker_compose
from utils.nginx import prepare_nginx, nginx_confd_dir
from utils.redis import prepare_redis
from g import (config_dir, input_config_path, private_key_pem_path, root_crt_path, secret_key_dir,
old_private_key_pem_path, old_crt_path)
# Main function
@click.command()
@click.option('--conf', default=input_config_path, help="the path of Harbor configuration file")
@click.option('--with-notary', is_flag=True, help="the Harbor instance is to be deployed with notary")
@click.option('--with-clair', is_flag=True, help="the Harbor instance is to be deployed with clair")
@click.option('--with-trivy', is_flag=True, help="the Harbor instance is to be deployed with Trivy")
@click.option('--with-chartmuseum', is_flag=True, help="the Harbor instance is to be deployed with chart repository supporting")
def main(conf, with_notary, with_clair, with_trivy, with_chartmuseum):
@click.group()
def cli():
pass
delfile(config_dir)
config_dict = parse_yaml_config(conf, with_notary=with_notary, with_clair=with_clair, with_trivy=with_trivy, with_chartmuseum=with_chartmuseum)
try:
validate(config_dict, notary_mode=with_notary)
except Exception as e:
logging.info('Error happened in config validation...')
logging.error(e)
sys.exit(-1)
prepare_log_configs(config_dict)
prepare_nginx(config_dict)
prepare_core(config_dict, with_notary=with_notary, with_clair=with_clair, with_trivy=with_trivy, with_chartmuseum=with_chartmuseum)
prepare_registry(config_dict)
prepare_registry_ctl(config_dict)
prepare_db(config_dict)
prepare_job_service(config_dict)
prepare_redis(config_dict)
get_secret_key(secret_key_dir)
# If Customized cert enabled
prepare_ca(
private_key_pem_path=private_key_pem_path,
root_crt_path=root_crt_path,
old_private_key_pem_path=old_private_key_pem_path,
old_crt_path=old_crt_path)
if with_notary:
prepare_notary(config_dict, nginx_confd_dir, SSL_CERT_PATH, SSL_CERT_KEY_PATH)
if with_clair:
prepare_clair(config_dict)
prepare_clair_adapter(config_dict)
if with_trivy:
prepare_trivy_adapter(config_dict)
if with_chartmuseum:
prepare_chartmuseum(config_dict)
prepare_docker_compose(config_dict, with_clair, with_trivy, with_notary, with_chartmuseum)
cli.add_command(prepare)
cli.add_command(gencert)
if __name__ == '__main__':
main()
cli()

View File

@ -0,0 +1,140 @@
import os
import logging
from pathlib import Path
from shutil import copytree, rmtree
from g import internal_tls_dir, DEFAULT_GID, DEFAULT_UID, PG_GID, PG_UID
from utils.misc import check_permission, owner_can_read, get_realpath
class InternalTLS:
harbor_certs_filename = {
'harbor_internal_ca.crt',
'proxy.crt', 'proxy.key',
'core.crt', 'core.key',
'job_service.crt', 'job_service.key',
'registryctl.crt', 'registryctl.key',
'registry.crt', 'registry.key'
}
clair_certs_filename = {
'clair_adapter.crt', 'clair_adapter.key',
'clair.crt', 'clair.key'
}
trivy_certs_filename = {
'trivy_adapter.crt', 'trivy_adapter.key',
}
notary_certs_filename = {
'notary_signer.crt', 'notary_signer.key',
'notary_server.crt', 'notary_server.key'
}
chart_museum_filename = {
'chartmuseum.crt',
'chartmuseum.key'
}
db_certs_filename = {
'harbor_db.crt', 'harbor_db.key'
}
def __init__(self, tls_enabled=False, verify_client_cert=False, tls_dir='', data_volume='', **kwargs):
self.data_volume = data_volume
self.verify_client_cert = verify_client_cert
self.enabled = tls_enabled
self.tls_dir = tls_dir
if self.enabled:
self.required_filenames = self.harbor_certs_filename
if kwargs.get('with_clair'):
self.required_filenames.update(self.clair_certs_filename)
if kwargs.get('with_notary'):
self.required_filenames.update(self.notary_certs_filename)
if kwargs.get('with_chartmuseum'):
self.required_filenames.update(self.chart_museum_filename)
if kwargs.get('with_trivy'):
self.required_filenames.update(self.trivy_certs_filename)
if not kwargs.get('external_database'):
self.required_filenames.update(self.db_certs_filename)
def __getattribute__(self, name: str):
"""
Make the call like 'internal_tls.core_crt_path' possible
"""
# only handle when enabled tls and name ends with 'path'
if name.endswith('_path'):
if not (self.enabled):
return object.__getattribute__(self, name)
name_parts = name.split('_')
if len(name_parts) < 3:
return object.__getattribute__(self, name)
filename = '{}.{}'.format('_'.join(name_parts[:-2]), name_parts[-2])
if filename in self.required_filenames:
return os.path.join(self.data_volume, 'secret', 'tls', filename)
return object.__getattribute__(self, name)
def _check(self, filename: str):
"""
Check the permission of cert and key is correct
"""
path = Path(os.path.join(internal_tls_dir, filename))
if not path.exists:
if filename == 'harbor_internal_ca.crt':
return
raise Exception('File {} not exist'.format(filename))
if not path.is_file:
raise Exception('invalid {}'.format(filename))
# check key file permission
if filename.endswith('.key') and not check_permission(path, mode=0o600):
raise Exception('key file {} permission is not 600'.format(filename))
# check owner can read cert file
if filename.endswith('.crt') and not owner_can_read(path.stat().st_mode):
raise Exception('File {} should readable by owner'.format(filename))
def validate(self) -> bool:
if not self.enabled:
return True
if not internal_tls_dir.exists():
raise Exception('Internal dir for tls {} not exist'.format(internal_tls_dir))
for filename in self.required_filenames:
self._check(filename)
return True
def prepare(self):
"""
Prepare moves certs in tls file to data volume with correct permission.
"""
if not self.enabled:
logging.info('internal tls NOT enabled...')
return
original_tls_dir = get_realpath(self.tls_dir)
if internal_tls_dir.exists():
rmtree(internal_tls_dir)
copytree(original_tls_dir, internal_tls_dir, symlinks=True)
for file in internal_tls_dir.iterdir():
if file.name.endswith('.key'):
file.chmod(0o600)
elif file.name.endswith('.crt'):
file.chmod(0o644)
if file.name in self.db_certs_filename:
os.chown(file, PG_UID, PG_GID)
else:
os.chown(file, DEFAULT_UID, DEFAULT_GID)

View File

@ -0,0 +1,139 @@
#! /bin/bash
set -e
if [ -z "$1" ]; then
echo "No argument supplied set days to 365"
DAYS=365
else
echo "No argument supplied set days to $1"
DAYS=$1
fi
CA_KEY="harbor_internal_ca.key"
CA_CRT="harbor_internal_ca.crt"
# CA key and certificate
if [[ ! -f $CA_KEY && ! -f $CA_CRT ]]; then
openssl req -x509 -nodes -days $DAYS -newkey rsa:4096 \
-keyout $CA_KEY -out $CA_CRT \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware"
else
echo "$CA_KEY and $CA_CRT exist, use them to generate certs"
fi
# generate proxy key and csr
openssl req -new -newkey rsa:4096 -nodes -sha256 \
-keyout proxy.key \
-out proxy.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=proxy"
# Sign proxy
openssl x509 -req -days $DAYS -sha256 -in proxy.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out proxy.crt
# generate core key and csr
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout core.key \
-out core.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=core"
# Sign core csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in core.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out core.crt
# job_service key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout job_service.key \
-out job_service.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=jobservice"
# sign job_service csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in job_service.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out job_service.crt
# generate registry key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout registry.key \
-out registry.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=registry"
# sign registry csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in registry.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out registry.crt
# generate registryctl key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout registryctl.key \
-out registryctl.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=registryctl"
# sign registryctl csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in registryctl.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out registryctl.crt
# generate clair_adapter key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout clair_adapter.key \
-out clair_adapter.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=clair-adapter"
# sign clair_adapter csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in clair_adapter.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out clair_adapter.crt
# generate clair key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout clair.key \
-out clair.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=clair"
# sign clair csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in clair.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out clair.crt
# generate trivy_adapter key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout trivy_adapter.key \
-out trivy_adapter.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=trivy-adapter"
# sign trivy_adapter csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in trivy_adapter.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out trivy_adapter.crt
# generate notary_signer key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout notary_signer.key \
-out notary_signer.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=notary_signer"
# sign notary_signer csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in notary_signer.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out notary_signer.crt
# generate notary_server key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout notary_server.key \
-out notary_server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=notary_server"
# sign notary_server csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in notary_server.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out notary_server.crt
# generate chartmuseum key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout chartmuseum.key \
-out chartmuseum.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=chartmuseum"
# sign chartmuseum csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in chartmuseum.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out chartmuseum.crt
# generate harbor_db key
openssl req -new \
-newkey rsa:4096 -nodes -sha256 -keyout harbor_db.key \
-out harbor_db.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=VMware/CN=harbor_db"
# sign harbor_db csr with CA certificate and key
openssl x509 -req -days $DAYS -sha256 -in harbor_db.csr -CA harbor_internal_ca.crt -CAkey harbor_internal_ca.key -CAcreateserial -out harbor_db.crt

View File

@ -1,5 +1,13 @@
## Settings should be set
{%if internal_tls.enabled %}
PORT=9443
TLS_CERT=/etc/harbor/ssl/chartmuseum.crt
TLS_KEY=/etc/harbor/ssl/chartmuseum.key
# Uncomment if need mTLS
# TLS_CA_CERT=/etc/harbor/ssl/harbor_internal_ca.crt
{% else %}
PORT=9999
{% endif %}
# Only support redis now. If redis is setup, then enable cache
CACHE={{cache_store}}
@ -34,8 +42,6 @@ CHART_URL={{public_url}}/chartrepo
CHART_URL=
{% endif %}
AUTH_ANONYMOUS_GET=false
TLS_CERT=
TLS_KEY=
CONTEXT_PATH=
INDEX_LIMIT=0
MAX_STORAGE_OBJECTS=0

View File

@ -1,4 +1,10 @@
SCANNER_LOG_LEVEL={{log_level}}
SCANNER_CLAIR_URL={{clair_url}}
SCANNER_CLAIR_DATABASE_URL=postgresql://{{clair_db_username}}:{{clair_db_password}}@{{clair_db_host}}:{{clair_db_port}}/{{clair_db_name}}?sslmode={{clair_db_sslmode}}
SCANNER_STORE_REDIS_URL={{redis_url_clair}}
SCANNER_STORE_REDIS_URL={{redis_url_clair}}
{%if internal_tls.enabled %}
SCANNER_API_SERVER_ADDR=:8443
SCANNER_API_SERVER_TLS_CERTIFICATE=/etc/harbor/ssl/clair_adapter.crt
SCANNER_API_SERVER_TLS_KEY=/etc/harbor/ssl/clair_adapter.key
{% endif %}

View File

@ -52,3 +52,10 @@ CSRF_KEY={{csrf_key}}
HTTP_PROXY={{core_http_proxy}}
HTTPS_PROXY={{core_https_proxy}}
NO_PROXY={{core_no_proxy}}
{%if internal_tls.enabled %}
INTERNAL_TLS_ENABLED=true
INTERNAL_TLS_KEY_PATH=/etc/harbor/ssl/core.key
INTERNAL_TLS_CERT_PATH=/etc/harbor/ssl/core.crt
INTERNAL_TLS_TRUST_CA_PATH=/harbor_cust_cert/harbor_internal_ca.crt
{% endif %}

View File

@ -41,10 +41,19 @@ services:
source: {{gcs_keyfile}}
target: /etc/registry/gcs.key
{% endif %}
{%if registry_custom_ca_bundle_path %}
{%if internal_tls.enabled %}
- type: bind
source: {{registry_custom_ca_bundle_path}}
target: /harbor_cust_cert/custom-ca-bundle.crt
source: {{internal_tls.core_key_path}}
target: /harbor_cust_cert/core.crt
- type: bind
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /harbor_cust_cert/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.registry_crt_path}}
target: /etc/harbor/tls/registry.crt
- type: bind
source: {{internal_tls.registry_key_path}}
target: /etc/harbor/tls/registry.key
{% endif %}
networks:
- harbor
@ -77,10 +86,16 @@ services:
- type: bind
source: ./common/config/registryctl/config.yml
target: /etc/registryctl/config.yml
{%if registry_custom_ca_bundle_path %}
{%if internal_tls.enabled %}
- type: bind
source: {{registry_custom_ca_bundle_path}}
target: /harbor_cust_cert/custom-ca-bundle.crt
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /harbor_cust_cert/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.registryctl_crt_path}}
target: /etc/harbor/ssl/registryctl.crt
- type: bind
source: {{internal_tls.registryctl_key_path}}
target: /etc/harbor/ssl/registryctl.key
{% endif %}
networks:
- harbor
@ -157,6 +172,17 @@ services:
- type: bind
source: {{uaa_ca_file}}
target: /etc/core/certificates/uaa_ca.pem
{% endif %}
{%if internal_tls.enabled %}
- type: bind
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /harbor_cust_cert/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.core_crt_path}}
target: /etc/harbor/ssl/core.crt
- type: bind
source: {{internal_tls.core_key_path}}
target: /etc/harbor/ssl/core.key
{% endif %}
networks:
harbor:
@ -227,6 +253,17 @@ services:
- type: bind
source: ./common/config/jobservice/config.yml
target: /etc/jobservice/config.yml
{%if internal_tls.enabled %}
- type: bind
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /harbor_cust_cert/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.job_service_crt_path}}
target: /etc/harbor/ssl/job_service.crt
- type: bind
source: {{internal_tls.job_service_key_path}}
target: /etc/harbor/ssl/job_service.key
{% endif %}
networks:
- harbor
{% if with_clair %}
@ -289,6 +326,17 @@ services:
- ./common/config/nginx:/etc/nginx:z
{% if protocol == 'https' %}
- {{data_volume}}/secret/cert:/etc/cert:z
{% endif %}
{%if internal_tls.enabled %}
- type: bind
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /etc/harbor/tls/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.proxy_crt_path}}
target: /etc/harbor/tls/proxy.crt
- type: bind
source: {{internal_tls.proxy_key_path}}
target: /etc/harbor/tls/proxy.key
{% endif %}
networks:
- harbor
@ -331,6 +379,17 @@ services:
- type: bind
source: {{data_volume}}/secret/registry/root.crt
target: /etc/notary/root.crt
{%if internal_tls.enabled %}
- type: bind
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /etc/harbor/ssl/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.notary_server_crt_path}}
target: /etc/harbor/ssl/notary_server.crt
- type: bind
source: {{internal_tls.notary_server_key_path}}
target: /etc/harbor/ssl/notary_server.key
{% endif %}
env_file:
- ./common/config/notary/server_env
depends_on:
@ -361,6 +420,17 @@ services:
- type: bind
source: {{data_volume}}/secret/notary/notary-signer.key
target: /etc/notary/notary-signer.key
{%if internal_tls.enabled %}
- type: bind
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /etc/harbor/ssl/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.notary_signer_crt_path}}
target: /etc/harbor/ssl/notary_signer.crt
- type: bind
source: {{internal_tls.notary_signer_key_path}}
target: /etc/harbor/ssl/notary_signer.key
{% endif %}
env_file:
- ./common/config/notary/signer_env
depends_on:
@ -398,11 +468,17 @@ services:
- type: bind
source: ./common/config/clair/config.yaml
target: /etc/clair/config.yaml
{%if registry_custom_ca_bundle_path %}
{%if internal_tls.enabled %}
- type: bind
source: {{registry_custom_ca_bundle_path}}
target: /harbor_cust_cert/custom-ca-bundle.crt
{% endif %}
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /harbor_cust_cert/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.clair_crt_path}}
target: /etc/harbor/ssl/clair.crt
- type: bind
source: {{internal_tls.clair_key_path}}
target: /etc/harbor/ssl/clair.key
{% endif %}
logging:
driver: "syslog"
options:
@ -428,6 +504,18 @@ services:
- clair
{% if external_redis == False %}
- redis
{% endif %}
{%if internal_tls.enabled %}
volumes:
- type: bind
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /harbor_cust_cert/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.clair_adapter_crt_path}}
target: /etc/harbor/ssl/clair_adapter.crt
- type: bind
source: {{internal_tls.clair_adapter_key_path}}
target: /etc/harbor/ssl/clair_adapter.key
{% endif %}
logging:
driver: "syslog"
@ -458,6 +546,18 @@ services:
- type: bind
source: {{data_volume}}/trivy-adapter/reports
target: /home/scanner/.cache/reports
{%if internal_tls.enabled %}
volumes:
- type: bind
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /harbor_cust_cert/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.trivy_adapter_crt_path}}
target: /etc/harbor/ssl/trivy_adapter.crt
- type: bind
source: {{internal_tls.trivy_adapter_key_path}}
target: /etc/harbor/ssl/trivy_adapter.key
{% endif %}
logging:
driver: "syslog"
options:
@ -486,15 +586,21 @@ services:
volumes:
- {{data_volume}}/chart_storage:/chart_storage:z
- ./common/config/chartserver:/etc/chartserver:z
{%if internal_tls.enabled %}
- type: bind
source: {{internal_tls.harbor_internal_ca_crt_path}}
target: /etc/harbor/ssl/harbor_internal_ca.crt
- type: bind
source: {{internal_tls.chartmuseum_crt_path}}
target: /etc/harbor/ssl/chartmuseum.crt
- type: bind
source: {{internal_tls.chartmuseum_key_path}}
target: /etc/harbor/ssl/chartmuseum.key
{% endif %}
{% if gcs_keyfile %}
- type: bind
source: {{gcs_keyfile}}
target: /etc/chartserver/gcs.key
{% endif %}
{%if registry_custom_ca_bundle_path %}
- type: bind
source: {{registry_custom_ca_bundle_path}}
target: /harbor_cust_cert/custom-ca-bundle.crt
{% endif %}
logging:
driver: "syslog"

View File

@ -1,14 +1,20 @@
---
#Protocol used to serve
protocol: "http"
{% if internal_tls.enabled %}
protocol: "https"
#Config certification if use 'https' protocol
#https_config:
# cert: "server.crt"
# key: "server.key"
https_config:
cert: "/etc/harbor/ssl/job_service.crt"
key: "/etc/harbor/ssl/job_service.key"
#Server listening port
port: 8443
{% else %}
protocol: "http"
#Server listening port
port: 8080
{% endif %}
#Worker pool
worker_pool:

View File

@ -1,10 +1,22 @@
CORE_SECRET={{core_secret}}
REGISTRY_URL={{registry_url}}
JOBSERVICE_SECRET={{jobservice_secret}}
CORE_URL={{core_url}}
REGISTRY_CONTROLLER_URL={{registry_controller_url}}
JOBSERVICE_WEBHOOK_JOB_MAX_RETRY={{notification_webhook_job_max_retry}}
{%if internal_tls.enabled %}
INTERNAL_TLS_ENABLED=true
INTERNAL_TLS_TRUST_CA_PATH=/harbor_cust_cert/harbor_internal_ca.crt
INTERNAL_TLS_KEY_PATH=/etc/harbor/ssl/job_service.key
INTERNAL_TLS_CERT_PATH=/etc/harbor/ssl/job_service.crt
{% endif %}
{% if internal_tls.verify_client_cert %}
INTERNAL_VERIFY_CLIENT_CERT=true
{% endif %}
HTTP_PROXY={{jobservice_http_proxy}}
HTTPS_PROXY={{jobservice_https_proxy}}
NO_PROXY={{jobservice_no_proxy}}
REGISTRY_CREDENTIAL_USERNAME={{registry_username}}
REGISTRY_CREDENTIAL_PASSWORD={{registry_password}}
REGISTRY_CREDENTIAL_PASSWORD={{registry_password}}

View File

@ -20,7 +20,11 @@ http {
proxy_http_version 1.1;
upstream core {
{% if internal_tls.enabled %}
server core:8443;
{% else %}
server core:8080;
{% endif %}
}
upstream portal {
@ -80,7 +84,18 @@ http {
}
location /c/ {
{% if internal_tls.enabled %}
proxy_pass https://core/c/;
proxy_ssl_certificate /etc/harbor/tls/proxy.crt;
proxy_ssl_certificate_key /etc/harbor/tls/proxy.key;
proxy_ssl_trusted_certificate /etc/harbor/tls/harbor_internal_ca.crt;
proxy_ssl_verify_depth 2;
proxy_ssl_verify on;
proxy_ssl_session_reuse on;
{% else %}
proxy_pass http://core/c/;
{% endif %}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@ -95,7 +110,18 @@ http {
}
location /api/ {
{% if internal_tls.enabled %}
proxy_pass https://core/api/;
proxy_ssl_certificate /etc/harbor/tls/proxy.crt;
proxy_ssl_certificate_key /etc/harbor/tls/proxy.key;
proxy_ssl_trusted_certificate /etc/harbor/tls/harbor_internal_ca.crt;
proxy_ssl_verify_depth 2;
proxy_ssl_verify on;
proxy_ssl_session_reuse on;
{% else %}
proxy_pass http://core/api/;
{% endif %}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@ -110,7 +136,18 @@ http {
}
location /chartrepo/ {
{% if internal_tls.enabled %}
proxy_pass https://core/chartrepo/;
proxy_ssl_certificate /etc/harbor/tls/proxy.crt;
proxy_ssl_certificate_key /etc/harbor/tls/proxy.key;
proxy_ssl_trusted_certificate /etc/harbor/tls/harbor_internal_ca.crt;
proxy_ssl_verify_depth 2;
proxy_ssl_verify on;
proxy_ssl_session_reuse on;
{% else %}
proxy_pass http://core/chartrepo/;
{% endif %}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@ -129,7 +166,18 @@ http {
}
location /v2/ {
{% if internal_tls.enabled %}
proxy_pass https://core/v2/;
proxy_ssl_certificate /etc/harbor/tls/proxy.crt;
proxy_ssl_certificate_key /etc/harbor/tls/proxy.key;
proxy_ssl_trusted_certificate /etc/harbor/tls/harbor_internal_ca.crt;
proxy_ssl_verify_depth 2;
proxy_ssl_verify on;
proxy_ssl_session_reuse on;
{% else %}
proxy_pass http://core/v2/;
{% endif %}
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@ -141,7 +189,18 @@ http {
}
location /service/ {
{% if internal_tls.enabled %}
proxy_pass https://core/service/;
proxy_ssl_certificate /etc/harbor/tls/proxy.crt;
proxy_ssl_certificate_key /etc/harbor/tls/proxy.key;
proxy_ssl_trusted_certificate /etc/harbor/tls/harbor_internal_ca.crt;
proxy_ssl_verify_depth 2;
proxy_ssl_verify on;
proxy_ssl_session_reuse on;
{% else %}
proxy_pass http://core/service/;
{% endif %}
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

View File

@ -21,10 +21,20 @@ redis:
password: {{redis_password}}
db: {{redis_db_index_reg}}
http:
{% if internal_tls.enabled %}
addr: :5443
{% else %}
addr: :5000
{% endif %}
secret: placeholder
debug:
addr: localhost:5001
{% if internal_tls.enabled %}
tls:
certificate: /etc/harbor/tls/registry.crt
key: /etc/harbor/tls/registry.key
{% endif %}
auth:
htpasswd:
realm: harbor-registry-basic-realm

View File

@ -1,8 +1,14 @@
---
{% if internal_tls.enabled %}
protocol: "https"
port: 8443
https_config:
cert: "/etc/harbor/ssl/registryctl.crt"
key: "/etc/harbor/ssl/registryctl.key"
{% else %}
protocol: "http"
port: 8080
{% endif %}
log_level: "INFO"
#https_config:
# cert: "server.crt"
# key: "server.key"

View File

@ -1,3 +1,11 @@
CORE_SECRET={{core_secret}}
JOBSERVICE_SECRET={{jobservice_secret}}
{%if internal_tls.enabled %}
INTERNAL_TLS_ENABLED=true
INTERNAL_TLS_TRUST_CA_PATH=/harbor_cust_cert/harbor_internal_ca.crt
INTERNAL_TLS_KEY_PATH=/etc/harbor/ssl/registryctl.key
INTERNAL_TLS_CERT_PATH=/etc/harbor/ssl/registryctl.crt
{% endif %}
{% if internal_tls.verify_client_cert %}
INTERNAL_VERIFY_CLIENT_CERT=true
{% endif %}

View File

@ -12,3 +12,8 @@ SCANNER_TRIVY_GITHUB_TOKEN={{trivy_github_token}}
HTTP_PROXY={{trivy_http_proxy}}
HTTPS_PROXY={{trivy_https_proxy}}
NO_PROXY={{trivy_no_proxy}}
{%if internal_tls.enabled %}
SCANNER_API_SERVER_ADDR=:8443
SCANNER_API_SERVER_TLS_KEY=/etc/harbor/ssl/trivy_adapter.key
SCANNER_API_SERVER_TLS_CERTIFICATE=/etc/harbor/ssl/trivy_adapter.crt
{% endif %}

View File

@ -3,18 +3,17 @@ import os, subprocess, shutil
from pathlib import Path
from subprocess import DEVNULL
from g import DEFAULT_GID, DEFAULT_UID
from g import DEFAULT_GID, DEFAULT_UID, trust_ca_dir, storage_ca_bundle_filename
from .misc import (
mark_file,
generate_random_string,
check_permission,
stat_decorator)
stat_decorator,
get_realpath)
SSL_CERT_PATH = os.path.join("/etc/cert", "server.crt")
SSL_CERT_KEY_PATH = os.path.join("/etc/cert", "server.key")
secret_keys_dir = '/secret/keys'
def _get_secret(folder, filename, length=16):
key_file = os.path.join(folder, filename)
if os.path.isfile(key_file):
@ -72,7 +71,7 @@ def openssl_installed():
return True
def prepare_ca(
def prepare_registry_ca(
private_key_pem_path: Path,
root_crt_path: Path,
old_private_key_pem_path: Path,
@ -97,4 +96,36 @@ def prepare_ca(
os.chown(root_crt_path, DEFAULT_UID, DEFAULT_GID)
if not check_permission(private_key_pem_path, uid=DEFAULT_UID, gid=DEFAULT_GID):
os.chown(private_key_pem_path, DEFAULT_UID, DEFAULT_GID)
os.chown(private_key_pem_path, DEFAULT_UID, DEFAULT_GID)
def prepare_trust_ca(**kwargs):
def f(path: str, file_name: str):
# check if source file valied
src_path = kwargs.get(path)
if not src_path:
return
real_path = get_realpath(src_path)
if not real_path.exists():
raise Exception('ca file {} is not exist'.format(real_path))
if not real_path.is_file():
raise Exception('{} is not file'.format(real_path))
dst_path = trust_ca_dir.joinpath(file_name)
# check destination dir exist
if not trust_ca_dir.exists():
trust_ca_dir.mkdir(parents=True)
else:
os.remove(dst_path)
# copy src to dst
shutil.copy(src_path, dst_path)
# change ownership and permission
mark_file(dst_path)
for p in (
('internal_https_ca_path', 'harbor_internal_ca.crt'),
('registry_custom_ca_bundle_path', storage_ca_bundle_filename)):
f(*p)

View File

@ -105,4 +105,5 @@ def prepare_chartmuseum(config_dict):
storage_driver=storage_driver,
all_storage_driver_configs=all_storage_provider_configs,
public_url=config_dict['public_url'],
chart_absolute_url=config_dict['chart_absolute_url'])
chart_absolute_url=config_dict['chart_absolute_url'],
internal_tls=config_dict['internal_tls'])

View File

@ -1,6 +1,8 @@
import os
import yaml
import logging
from models import InternalTLS
from g import versions_file_path, host_root_dir, DEFAULT_UID, INTERNAL_NO_PROXY_DN
from utils.misc import generate_random_string, owner_can_read, other_can_read
@ -104,12 +106,11 @@ def parse_yaml_config(config_file_path, with_notary, with_clair, with_trivy, wit
configs = yaml.load(f)
config_dict = {
'adminserver_url': "http://adminserver:8080",
'registry_url': "http://registry:5000",
'registry_controller_url': "http://registryctl:8080",
'core_url': "http://core:8080",
'core_local_url': "http://127.0.0.1:8080",
'token_service_url': "http://core:8080/service/token",
'registry_url': 'http://registry:5000',
'registry_controller_url': 'http://registryctl:8080',
'core_url': 'http://core:8080',
'core_local_url': 'http://127.0.0.1:8080',
'token_service_url': 'http://core:8080/service/token',
'jobservice_url': 'http://jobservice:8080',
'clair_url': 'http://clair:6060',
'clair_adapter_url': 'http://clair-adapter:8080',
@ -333,6 +334,35 @@ def parse_yaml_config(config_file_path, with_notary, with_clair, with_trivy, wit
config_dict['registry_username'] = REGISTRY_USER_NAME
config_dict['registry_password'] = generate_random_string(32)
internal_tls_config = configs['internal_tls']
# TLS related configs
if internal_tls_config.get('enabled'):
config_dict['internal_tls'] = InternalTLS(
internal_tls_config['enabled'],
internal_tls_config['verify_client_cert'],
internal_tls_config['dir'],
configs['data_volume'],
with_notary=with_notary,
with_clair=with_clair,
with_trivy=with_trivy,
with_chartmuseum=with_chartmuseum,
external_database=config_dict['external_database'])
else:
config_dict['internal_tls'] = InternalTLS()
if config_dict['internal_tls'].enabled:
config_dict['registry_url'] = 'https://registry:5443'
config_dict['registry_controller_url'] = 'https://registryctl:8443'
config_dict['core_url'] = 'https://core:8443'
config_dict['core_local_url'] = 'https://core:8443'
config_dict['token_service_url'] = 'https://core:8443/service/token'
config_dict['jobservice_url'] = 'https://jobservice:8443'
config_dict['clair_adapter_url'] = 'https://clair-adapter:8443'
config_dict['trivy_adapter_url'] = 'https://trivy-adapter:8443'
# config_dict['notary_url'] = 'http://notary-server:4443'
config_dict['chart_repository_url'] = 'https://chartmuseum:9443'
return config_dict

View File

@ -25,7 +25,6 @@ def prepare_docker_compose(configs, with_clair, with_trivy, with_notary, with_ch
'log_location': configs['log_location'],
'protocol': configs['protocol'],
'http_port': configs['http_port'],
'registry_custom_ca_bundle_path': configs['registry_custom_ca_bundle_path'],
'external_redis': configs['external_redis'],
'external_database': configs['external_database'],
'with_notary': with_notary,
@ -34,6 +33,10 @@ def prepare_docker_compose(configs, with_clair, with_trivy, with_notary, with_ch
'with_chartmuseum': with_chartmuseum
}
# if configs.get('registry_custom_ca_bundle_path'):
# rendering_variables['registry_custom_ca_bundle_path'] = configs.get('registry_custom_ca_bundle_path')
# rendering_variables['custom_ca_required'] = True
# for gcs
storage_config = configs.get('storage_provider_config') or {}
if storage_config.get('keyfile') and configs['storage_provider_name'] == 'gcs':
@ -45,6 +48,9 @@ def prepare_docker_compose(configs, with_clair, with_trivy, with_notary, with_ch
rendering_variables['cert_path'] = configs['cert_path']
rendering_variables['https_port'] = configs['https_port']
# internal cert pairs
rendering_variables['internal_tls'] = configs['internal_tls']
# for uaa
uaa_config = configs.get('uaa') or {}
if uaa_config.get('ca_file'):

View File

@ -0,0 +1,4 @@
def prepare_tls(config_dict):
config_dict['internal_tls'].prepare()
config_dict['internal_tls'].validate()

View File

@ -30,6 +30,7 @@ def prepare_job_service(config_dict):
jobservice_conf,
uid=DEFAULT_UID,
gid=DEFAULT_GID,
internal_tls=config_dict['internal_tls'],
max_job_workers=config_dict['max_job_workers'],
redis_url=config_dict['redis_url_js'],
level=log_level)

View File

@ -3,7 +3,7 @@ import secrets
from pathlib import Path
from functools import wraps
from g import DEFAULT_UID, DEFAULT_GID
from g import DEFAULT_UID, DEFAULT_GID, host_root_dir
# To meet security requirement
# By default it will change file mode to 0600, and make the owner of the file to 10000:10000
@ -168,3 +168,12 @@ def stat_decorator(func):
return check_wrapper
def get_realpath(path: str) -> Path:
"""
Return the real path in your host if you mounted your host's filesystem to /hostfs,
or return the original path
"""
if os.path.isdir(host_root_dir):
return os.path.join(host_root_dir, path.lstrip('/'))
return Path(path)

View File

@ -61,7 +61,8 @@ def render_nginx_template(config_dict):
gid=DEFAULT_GID,
https_redirect='$host' + ('https_port' in config_dict and (":" + str(config_dict['https_port'])) or ""),
ssl_cert=SSL_CERT_PATH,
ssl_cert_key=SSL_CERT_KEY_PATH)
ssl_cert_key=SSL_CERT_KEY_PATH,
internal_tls=config_dict['internal_tls'])
location_file_pattern = CUSTOM_NGINX_LOCATION_FILE_PATTERN_HTTPS
else:
@ -69,7 +70,8 @@ def render_nginx_template(config_dict):
nginx_http_conf_template,
nginx_conf,
uid=DEFAULT_UID,
gid=DEFAULT_GID)
gid=DEFAULT_GID,
internal_tls=config_dict['internal_tls'])
location_file_pattern = CUSTOM_NGINX_LOCATION_FILE_PATTERN_HTTP
copy_nginx_location_configs_if_exist(nginx_template_ext_dir, nginx_confd_dir, location_file_pattern)

View File

@ -1,5 +1,5 @@
import os, shutil, pathlib
from g import templates_dir, config_dir, root_crt_path, secret_key_dir,DEFAULT_UID, DEFAULT_GID
from g import templates_dir, config_dir, root_crt_path, secret_key_dir, secret_dir, DEFAULT_UID, DEFAULT_GID
from .cert import openssl_installed, create_cert, create_root_cert, get_alias
from .jinja import render_jinja
from .misc import mark_file, prepare_dir
@ -25,7 +25,7 @@ def prepare_env_notary(nginx_config_dir):
old_signer_key_secret_path = pathlib.Path(os.path.join(config_dir, 'notary-signer.key'))
old_signer_ca_cert_secret_path = pathlib.Path(os.path.join(config_dir, 'notary-signer-ca.crt'))
notary_secret_dir = prepare_dir('/secret/notary')
notary_secret_dir = prepare_dir(secret_dir ,'notary')
signer_cert_secret_path = pathlib.Path(os.path.join(notary_secret_dir, 'notary-signer.crt'))
signer_key_secret_path = pathlib.Path(os.path.join(notary_secret_dir, 'notary-signer.key'))
signer_ca_cert_secret_path = pathlib.Path(os.path.join(notary_secret_dir, 'notary-signer-ca.crt'))

View File

@ -1,6 +1,6 @@
import os, shutil
from g import config_dir, templates_dir
from g import config_dir, templates_dir, DEFAULT_GID, DEFAULT_UID
from utils.misc import prepare_dir
from utils.jinja import render_jinja
@ -12,19 +12,18 @@ registryctl_conf_env = os.path.join(config_dir, "registryctl", "env")
def prepare_registry_ctl(config_dict):
# prepare dir
prepare_registry_ctl_config_dir()
prepare_dir(registryctl_config_dir)
# Render Registryctl
# Render Registryctl env
render_jinja(
registryctl_env_template_path,
registryctl_conf_env,
**config_dict)
# Copy Registryctl config
copy_registry_ctl_conf(registryctl_config_template_path, registryctl_conf)
def prepare_registry_ctl_config_dir():
prepare_dir(registryctl_config_dir)
def copy_registry_ctl_conf(src, dst):
shutil.copyfile(src, dst)
# Render Registryctl config
render_jinja(
registryctl_config_template_path,
registryctl_conf,
uid=DEFAULT_UID,
gid=DEFAULT_GID,
**config_dict)

View File

@ -55,9 +55,8 @@ docker run --rm -v $input_dir:/input:z \
-v $data_path:/data:z \
-v $harbor_prepare_path:/compose_location:z \
-v $config_dir:/config:z \
-v $secret_dir:/secret:z \
-v /:/hostfs:z \
goharbor/prepare:dev $@
goharbor/prepare:dev prepare $@
echo "Clean up the input dir"
# Clean up input dir

View File

@ -7,6 +7,7 @@ import (
"net/http"
"net/url"
"strings"
"sync"
"time"
commonhttp "github.com/goharbor/harbor/src/common/http"
@ -19,6 +20,11 @@ const (
idleConnectionTimeout = 30 * time.Second
)
var (
once sync.Once
chartTransport *http.Transport
)
// ChartClient is a http client to get the content from the external http server
type ChartClient struct {
// HTTP client
@ -31,12 +37,15 @@ type ChartClient struct {
// NewChartClient is constructor of ChartClient
// credential can be nil
func NewChartClient(credential *Credential) *ChartClient { // Create http client with customized timeouts
once.Do(func() {
chartTransport = commonhttp.GetHTTPTransport(commonhttp.SecureTransport).Clone()
chartTransport.MaxIdleConns = maxIdleConnections
chartTransport.IdleConnTimeout = idleConnectionTimeout
})
client := &http.Client{
Timeout: clientTimeout,
Transport: &http.Transport{
MaxIdleConns: maxIdleConnections,
IdleConnTimeout: idleConnectionTimeout,
},
Timeout: clientTimeout,
Transport: chartTransport,
}
return &ChartClient{

View File

@ -17,6 +17,7 @@ import (
"github.com/goharbor/harbor/src/common"
"github.com/goharbor/harbor/src/common/api"
commonhttp "github.com/goharbor/harbor/src/common/http"
hlog "github.com/goharbor/harbor/src/common/utils/log"
n_event "github.com/goharbor/harbor/src/pkg/notifier/event"
"github.com/goharbor/harbor/src/replication"
@ -57,6 +58,7 @@ func NewProxyEngine(target *url.URL, cred *Credential, middlewares ...func(http.
director(target, cred, req)
},
ModifyResponse: modifyResponse,
Transport: commonhttp.GetHTTPTransport(commonhttp.SecureTransport),
}
if len(middlewares) > 0 {

View File

@ -2,7 +2,9 @@ package driver
import (
"errors"
"github.com/goharbor/harbor/src/common/http"
"net/http"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/http/modifier"
"github.com/goharbor/harbor/src/common/utils/log"
)
@ -10,12 +12,17 @@ import (
// RESTDriver - config store driver based on REST API
type RESTDriver struct {
configRESTURL string
client *http.Client
client *commonhttp.Client
}
// NewRESTDriver - Create RESTDriver
func NewRESTDriver(configRESTURL string, modifiers ...modifier.Modifier) *RESTDriver {
return &RESTDriver{configRESTURL: configRESTURL, client: http.NewClient(nil, modifiers...)}
if commonhttp.InternalTLSEnabled() {
tr := commonhttp.GetHTTPTransport(commonhttp.SecureTransport)
return &RESTDriver{configRESTURL: configRESTURL, client: commonhttp.NewClient(&http.Client{Transport: tr}, modifiers...)}
}
return &RESTDriver{configRESTURL: configRESTURL, client: commonhttp.NewClient(nil, modifiers...)}
}
// Load - load config data from REST server

View File

@ -16,18 +16,44 @@ package http
import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"github.com/goharbor/harbor/src/common/http/modifier"
"github.com/goharbor/harbor/src/internal"
"io"
"io/ioutil"
"net/http"
"net/url"
"reflect"
"github.com/goharbor/harbor/src/common/http/modifier"
"github.com/goharbor/harbor/src/internal"
)
const (
// InsecureTransport used to get the insecure http Transport
InsecureTransport = iota
// SecureTransport used to get the external secure http Transport
SecureTransport
)
var (
secureHTTPTransport *http.Transport
insecureHTTPTransport *http.Transport
)
func init() {
secureHTTPTransport = http.DefaultTransport.(*http.Transport).Clone()
insecureHTTPTransport = http.DefaultTransport.(*http.Transport).Clone()
insecureHTTPTransport.TLSClientConfig.InsecureSkipVerify = true
if InternalTLSEnabled() {
tlsConfig, err := GetInternalTLSConfig()
if err != nil {
panic(err)
}
secureHTTPTransport.TLSClientConfig = tlsConfig
}
}
// Client is a util for common HTTP operations, such Get, Head, Post, Put and Delete.
// Use Do instead if those methods can not meet your requirement
type Client struct {
@ -35,31 +61,22 @@ type Client struct {
client *http.Client
}
var defaultHTTPTransport, secureHTTPTransport, insecureHTTPTransport *http.Transport
func init() {
defaultHTTPTransport = &http.Transport{}
secureHTTPTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: false,
},
}
insecureHTTPTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
// GetHTTPTransport returns HttpTransport based on insecure configuration
func GetHTTPTransport(clientType uint) *http.Transport {
switch clientType {
case SecureTransport:
return secureHTTPTransport
case InsecureTransport:
return insecureHTTPTransport
default:
// default Transport is secure one
return secureHTTPTransport
}
}
// GetHTTPTransport returns HttpTransport based on insecure configuration
func GetHTTPTransport(insecure ...bool) *http.Transport {
if len(insecure) == 0 {
return defaultHTTPTransport
}
if insecure[0] {
// GetHTTPTransportByInsecure returns a insecure HttpTransport if insecure is true or it returns secure one
func GetHTTPTransportByInsecure(insecure bool) *http.Transport {
if insecure {
return insecureHTTPTransport
}
return secureHTTPTransport
@ -74,9 +91,7 @@ func NewClient(c *http.Client, modifiers ...modifier.Modifier) *Client {
}
if client.client == nil {
client.client = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
},
Transport: GetHTTPTransport(SecureTransport),
}
}
if len(modifiers) > 0 {

View File

@ -7,8 +7,8 @@ import (
)
func TestGetHTTPTransport(t *testing.T) {
transport := GetHTTPTransport(true)
transport := GetHTTPTransport(InsecureTransport)
assert.True(t, transport.TLSClientConfig.InsecureSkipVerify)
transport = GetHTTPTransport(false)
transport = GetHTTPTransport(SecureTransport)
assert.False(t, transport.TLSClientConfig.InsecureSkipVerify)
}

62
src/common/http/tls.go Normal file
View File

@ -0,0 +1,62 @@
// Copyright Project Harbor Authors
//
// 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.
package http
import (
"crypto/tls"
"fmt"
"os"
"strings"
)
const (
// Internal TLS ENV
internalTLSEnable = "INTERNAL_TLS_ENABLED"
internalVerifyClientCert = "INTERNAL_VERIFY_CLIENT_CERT"
internalTLSKeyPath = "INTERNAL_TLS_KEY_PATH"
internalTLSCertPath = "INTERNAL_TLS_CERT_PATH"
internalTrustCAPath = "INTERNAL_TLS_TRUST_CA_PATH"
)
// InternalTLSEnabled returns if internal TLS enabled
func InternalTLSEnabled() bool {
return strings.ToLower(os.Getenv(internalTLSEnable)) == "true"
}
// InternalEnableVerifyClientCert returns if mTLS enabled
func InternalEnableVerifyClientCert() bool {
return strings.ToLower(os.Getenv(internalVerifyClientCert)) == "true"
}
// GetInternalCertPair used to get internal cert and key pair from environment
func GetInternalCertPair() (tls.Certificate, error) {
crtPath := os.Getenv(internalTLSCertPath)
keyPath := os.Getenv(internalTLSKeyPath)
cert, err := tls.LoadX509KeyPair(crtPath, keyPath)
return cert, err
}
// GetInternalTLSConfig return a tls.Config for internal https communicate
func GetInternalTLSConfig() (*tls.Config, error) {
// genrate key pair
cert, err := GetInternalCertPair()
if err != nil {
return nil, fmt.Errorf("internal TLS enabled but can't get cert file %w", err)
}
return &tls.Config{
Certificates: []tls.Certificate{cert},
}, nil
}

View File

@ -62,10 +62,13 @@ func Init() {
// NewDefaultClient creates a default client based on endpoint and secret.
func NewDefaultClient(endpoint, secret string) *DefaultClient {
var c *commonhttp.Client
httpCli := &http.Client{
Transport: commonhttp.GetHTTPTransport(commonhttp.SecureTransport),
}
if len(secret) > 0 {
c = commonhttp.NewClient(nil, auth.NewSecretAuthorizer(secret))
c = commonhttp.NewClient(httpCli, auth.NewSecretAuthorizer(secret))
} else {
c = commonhttp.NewClient(nil)
c = commonhttp.NewClient(httpCli)
}
e := strings.TrimRight(endpoint, "/")
return &DefaultClient{
@ -74,7 +77,29 @@ func NewDefaultClient(endpoint, secret string) *DefaultClient {
}
}
// SubmitJob call jobserivce API to submit a job and returns the job's UUID.
// NewReplicationClient used to create a client for replication
func NewReplicationClient(endpoint, secret string) *DefaultClient {
var c *commonhttp.Client
if len(secret) > 0 {
c = commonhttp.NewClient(&http.Client{
Transport: commonhttp.GetHTTPTransport(commonhttp.SecureTransport),
},
auth.NewSecretAuthorizer(secret))
} else {
c = commonhttp.NewClient(&http.Client{
Transport: commonhttp.GetHTTPTransport(commonhttp.SecureTransport),
})
}
e := strings.TrimRight(endpoint, "/")
return &DefaultClient{
endpoint: e,
client: c,
}
}
// SubmitJob call jobservice API to submit a job and returns the job's UUID.
func (d *DefaultClient) SubmitJob(jd *models.JobData) (string, error) {
url := d.endpoint + "/api/v1/jobs"
jq := models.JobRequest{

View File

@ -131,7 +131,8 @@ func HTTPStatusCodeHealthChecker(method string, url string, header http.Header,
}
client := httputil.NewClient(&http.Client{
Timeout: timeout,
Transport: httputil.GetHTTPTransport(httputil.SecureTransport),
Timeout: timeout,
})
resp, err := client.Do(req)
if err != nil {

View File

@ -229,6 +229,11 @@ func InternalJobServiceURL() string {
return strings.TrimSuffix(cfgMgr.Get(common.JobServiceURL).GetString(), "/")
}
// GetCoreURL returns the url of core from env
func GetCoreURL() string {
return os.Getenv("CORE_URL")
}
// InternalCoreURL returns the local harbor core url
func InternalCoreURL() string {
return strings.TrimSuffix(cfgMgr.Get(common.CoreURL).GetString(), "/")
@ -409,7 +414,7 @@ func GetPortalURL() string {
// GetRegistryCtlURL returns the URL of registryctl
func GetRegistryCtlURL() string {
url := os.Getenv("REGISTRYCTL_URL")
url := os.Getenv("REGISTRY_CONTROLLER_URL")
if len(url) == 0 {
return common.DefaultRegistryCtlURL
}

View File

@ -26,6 +26,7 @@ import (
_ "github.com/astaxie/beego/session/redis"
_ "github.com/goharbor/harbor/src/api/event/handler"
"github.com/goharbor/harbor/src/common/dao"
common_http "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/job"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/common/utils"
@ -161,8 +162,19 @@ func main() {
server.RegisterRoutes()
log.Infof("Version: %s, Git commit: %s", version.ReleaseVersion, version.GitCommit)
if common_http.InternalTLSEnabled() {
log.Info("internal TLS enabled, Init TLS ...")
iTLSKeyPath := os.Getenv("INTERNAL_TLS_KEY_PATH")
iTLSCertPath := os.Getenv("INTERNAL_TLS_CERT_PATH")
log.Infof("load client key: %s client cert: %s", iTLSKeyPath, iTLSCertPath)
beego.BConfig.Listen.EnableHTTPS = true
beego.BConfig.Listen.HTTPSPort = 8443
beego.BConfig.Listen.HTTPSKeyFile = iTLSKeyPath
beego.BConfig.Listen.HTTPSCertFile = iTLSCertPath
}
log.Infof("Version: %s, Git commit: %s", version.ReleaseVersion, version.GitCommit)
beego.RunWithMiddleWares("", middlewares.MiddleWares()...)
}

View File

@ -1,43 +0,0 @@
// Copyright Project Harbor Authors
//
// 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.
package internal
import (
"crypto/tls"
"net/http"
)
var (
secureHTTPTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: false,
},
}
insecureHTTPTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
)
// GetHTTPTransport returns the HTTP transport based on insecure configuration
func GetHTTPTransport(insecure ...bool) *http.Transport {
if len(insecure) > 0 && insecure[0] {
return insecureHTTPTransport
}
return secureHTTPTransport
}

View File

@ -15,12 +15,13 @@
package api
import (
"context"
"crypto/tls"
"fmt"
"net/http"
"time"
"context"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/jobservice/config"
"github.com/goharbor/harbor/src/jobservice/logger"
)
@ -72,21 +73,11 @@ func NewServer(ctx context.Context, router Router, cfg ServerConfig) *Server {
}
// Initialize TLS/SSL config if protocol is https
if cfg.Protocol == config.JobServiceProtocolHTTPS {
tlsCfg := &tls.Config{
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
PreferServerCipherSuites: true,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
},
if cfg.Protocol == config.JobServiceProtocolHTTPS && commonhttp.InternalEnableVerifyClientCert() {
logger.Infof("mTLS enabled ...")
srv.TLSConfig = &tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
}
srv.TLSConfig = tlsCfg
srv.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0)
}
apiServer.httpServer = srv

View File

@ -15,6 +15,7 @@
package hook
import (
"context"
"encoding/json"
"errors"
"fmt"
@ -24,7 +25,8 @@ import (
"strings"
"time"
"context"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/utils/log"
)
// Client for handling the hook events
@ -54,6 +56,13 @@ func NewClient(ctx context.Context) Client {
ExpectContinueTimeout: 1 * time.Second,
Proxy: http.ProxyFromEnvironment,
}
if commonhttp.InternalEnableVerifyClientCert() {
tlsConfig, err := commonhttp.GetInternalTLSConfig()
if err != nil {
log.Errorf("client load cert file with err: %w", err)
}
transport.TLSClientConfig = tlsConfig
}
client := &http.Client{
Timeout: 15 * time.Second,

View File

@ -60,13 +60,17 @@ func (wj *WebhookJob) init(ctx job.Context, params map[string]interface{}) error
wj.logger = ctx.GetLogger()
wj.ctx = ctx
// default insecureSkipVerify is false
insecureSkipVerify := false
// default use insecure transport
tr := commonhttp.GetHTTPTransport(commonhttp.InsecureTransport)
if v, ok := params["skip_cert_verify"]; ok {
insecureSkipVerify = v.(bool)
if insecure, ok := v.(bool); ok {
if insecure {
tr = commonhttp.GetHTTPTransport(commonhttp.SecureTransport)
}
}
}
wj.client = &http.Client{
Transport: commonhttp.GetHTTPTransport(insecureSkipVerify),
Transport: tr,
}
return nil

View File

@ -16,7 +16,6 @@ package replication
import (
"fmt"
"github.com/goharbor/harbor/src/internal"
"net/http"
"os"
@ -61,7 +60,7 @@ func (s *Scheduler) Run(ctx job.Context, params job.Parameters) error {
policyID := (int64)(params["policy_id"].(float64))
cred := auth.NewSecretAuthorizer(os.Getenv("JOBSERVICE_SECRET"))
client := common_http.NewClient(&http.Client{
Transport: internal.GetHTTPTransport(true),
Transport: common_http.GetHTTPTransport(common_http.SecureTransport),
}, cred)
if err := client.Post(url, struct {
PolicyID int64 `json:"policy_id"`

View File

@ -230,6 +230,7 @@ func (bs *Bootstrap) createAPIServer(ctx context.Context, cfg *config.Configurat
Port: cfg.Port,
}
if cfg.HTTPSConfig != nil {
serverConfig.Protocol = config.JobServiceProtocolHTTPS
serverConfig.Cert = cfg.HTTPSConfig.Cert
serverConfig.Key = cfg.HTTPSConfig.Key
}

View File

@ -110,9 +110,8 @@ func (m *DefaultManager) policyHTTPTest(address string, skipCertVerify bool) err
}
req.Header.Set("Content-Type", "application/json")
client := http.Client{
Transport: commonhttp.GetHTTPTransport(skipCertVerify),
Transport: commonhttp.GetHTTPTransportByInsecure(skipCertVerify),
}
resp, err := client.Do(req)

View File

@ -16,25 +16,27 @@ package auth
import (
"fmt"
"net/http"
"net/url"
"strings"
"sync"
"github.com/docker/distribution/registry/client/auth/challenge"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/http/modifier"
"github.com/goharbor/harbor/src/internal"
"github.com/goharbor/harbor/src/pkg/registry/auth/basic"
"github.com/goharbor/harbor/src/pkg/registry/auth/bearer"
"github.com/goharbor/harbor/src/pkg/registry/auth/null"
"net/http"
"net/url"
"strings"
"sync"
)
// NewAuthorizer creates an authorizer that can handle different auth schemes
func NewAuthorizer(username, password string, insecure bool) internal.Authorizer {
func NewAuthorizer(username, password string, trType uint) internal.Authorizer {
return &authorizer{
username: username,
password: password,
client: &http.Client{
Transport: internal.GetHTTPTransport(insecure),
Transport: commonhttp.GetHTTPTransport(trType),
},
}
}

View File

@ -27,10 +27,10 @@ import (
"github.com/docker/distribution"
"github.com/docker/distribution/manifest/manifestlist"
// register oci manifest unmarshal function
_ "github.com/docker/distribution/manifest/ocischema"
_ "github.com/docker/distribution/manifest/ocischema" // register oci manifest unmarshal function
"github.com/docker/distribution/manifest/schema1"
"github.com/docker/distribution/manifest/schema2"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/core/config"
"github.com/goharbor/harbor/src/internal"
ierror "github.com/goharbor/harbor/src/internal/error"
@ -44,7 +44,7 @@ var (
Cli = func() Client {
url, _ := config.RegistryURL()
username, password := config.RegistryCredential()
return NewClient(url, username, password, true)
return NewClient(url, username, password, false)
}()
accepts = []string{
@ -99,22 +99,36 @@ type Client interface {
// of the registry automatically and calls the corresponding underlying authorizers(basic/bearer) to
// do the auth work. If a customized authorizer is needed, use "NewClientWithAuthorizer" instead
func NewClient(url, username, password string, insecure bool) Client {
var transportType uint
if insecure {
transportType = commonhttp.InsecureTransport
} else {
transportType = commonhttp.SecureTransport
}
return &client{
url: url,
authorizer: auth.NewAuthorizer(username, password, insecure),
authorizer: auth.NewAuthorizer(username, password, transportType),
client: &http.Client{
Transport: internal.GetHTTPTransport(insecure),
Transport: commonhttp.GetHTTPTransport(transportType),
},
}
}
// NewClientWithAuthorizer creates a registry client with the provided authorizer
func NewClientWithAuthorizer(url string, authorizer internal.Authorizer, insecure bool) Client {
var transportType uint
if insecure {
transportType = commonhttp.InsecureTransport
} else {
transportType = commonhttp.SecureTransport
}
return &client{
url: url,
authorizer: authorizer,
client: &http.Client{
Transport: internal.GetHTTPTransport(insecure),
Transport: commonhttp.GetHTTPTransport(transportType),
},
}
}

View File

@ -17,17 +17,17 @@ package notary
import (
"encoding/hex"
"fmt"
"github.com/goharbor/harbor/src/internal"
model2 "github.com/goharbor/harbor/src/pkg/signature/notary/model"
"net/http"
"os"
"path"
"strings"
"github.com/docker/distribution/registry/auth/token"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/core/config"
tokenutil "github.com/goharbor/harbor/src/core/service/token"
model2 "github.com/goharbor/harbor/src/pkg/signature/notary/model"
"github.com/theupdateframework/notary"
"github.com/theupdateframework/notary/client"
"github.com/theupdateframework/notary/trustpinning"
@ -82,7 +82,7 @@ func GetTargets(notaryEndpoint string, username string, fqRepo string) ([]model2
authorizer := &notaryAuthorizer{
token: t.Token,
}
tr := NewTransport(internal.GetHTTPTransport(), authorizer)
tr := NewTransport(commonhttp.GetHTTPTransport(commonhttp.SecureTransport), authorizer)
gun := data.GUN(fqRepo)
notaryRepo, err := client.NewFileCachedRepository(notaryCachePath, gun, notaryEndpoint, tr, mockRetriever, trustPin)
if err != nil {

View File

@ -57,7 +57,9 @@ func NewClient(baseURL string, cfg *Config) Client {
}
if cfg != nil {
authorizer := auth.NewSecretAuthorizer(cfg.Secret)
client.client = common_http.NewClient(nil, authorizer)
client.client = common_http.NewClient(&http.Client{
Transport: common_http.GetHTTPTransport(common_http.SecureTransport),
}, authorizer)
}
return client
}

View File

@ -19,6 +19,7 @@ import (
"flag"
"net/http"
common_http "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/registryctl/config"
"github.com/goharbor/harbor/src/registryctl/handlers"
@ -37,25 +38,13 @@ func (s *RegistryCtl) Start() {
Handler: s.Handler,
}
if s.ServerConf.Protocol == "HTTPS" {
tlsCfg := &tls.Config{
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
PreferServerCipherSuites: true,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
},
}
regCtl.TLSConfig = tlsCfg
regCtl.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0)
}
var err error
if s.ServerConf.Protocol == "HTTPS" {
if s.ServerConf.Protocol == "https" {
if common_http.InternalEnableVerifyClientCert() {
regCtl.TLSConfig = &tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
}
}
err = regCtl.ListenAndServeTLS(s.ServerConf.HTTPSConfig.Cert, s.ServerConf.HTTPSConfig.Key)
} else {
err = regCtl.ListenAndServe()

View File

@ -4,9 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/docker/distribution/registry/client/auth/challenge"
"github.com/goharbor/harbor/src/internal"
"github.com/goharbor/harbor/src/pkg/registry/auth/bearer"
"net/http"
"path/filepath"
"regexp"
@ -14,8 +12,11 @@ import (
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/cr"
"github.com/docker/distribution/registry/client/auth/challenge"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/utils"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/pkg/registry/auth/bearer"
adp "github.com/goharbor/harbor/src/replication/adapter"
"github.com/goharbor/harbor/src/replication/adapter/native"
"github.com/goharbor/harbor/src/replication/model"
@ -69,9 +70,13 @@ func newAdapter(registry *model.Registry) (*adapter, error) {
}
func ping(registry *model.Registry) (string, string, error) {
client := &http.Client{
Transport: internal.GetHTTPTransport(registry.Insecure),
client := &http.Client{}
if registry.Insecure {
client.Transport = commonhttp.GetHTTPTransport(commonhttp.InsecureTransport)
} else {
client.Transport = commonhttp.GetHTTPTransport(commonhttp.SecureTransport)
}
resp, err := client.Get(registry.URL + "/v2/")
if err != nil {
return "", "", err

View File

@ -16,7 +16,6 @@ package awsecr
import (
"errors"
"github.com/goharbor/harbor/src/internal"
"net/http"
"regexp"
@ -25,6 +24,7 @@ import (
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
awsecrapi "github.com/aws/aws-sdk-go/service/ecr"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/utils/log"
adp "github.com/goharbor/harbor/src/replication/adapter"
"github.com/goharbor/harbor/src/replication/adapter/native"
@ -245,11 +245,12 @@ func (a *adapter) createRepository(repository string) error {
if a.region == "" {
return errors.New("no region parsed")
}
config := &aws.Config{
Credentials: cred,
Region: &a.region,
HTTPClient: &http.Client{
Transport: internal.GetHTTPTransport(a.registry.Insecure),
Transport: commonhttp.GetHTTPTransportByInsecure(a.registry.Insecure),
},
}
if a.forceEndpoint != nil {
@ -287,11 +288,18 @@ func (a *adapter) DeleteManifest(repository, reference string) error {
if a.region == "" {
return errors.New("no region parsed")
}
var tr *http.Transport
if a.registry.Insecure {
tr = commonhttp.GetHTTPTransport(commonhttp.InsecureTransport)
} else {
tr = commonhttp.GetHTTPTransport(commonhttp.SecureTransport)
}
config := &aws.Config{
Credentials: cred,
Region: &a.region,
HTTPClient: &http.Client{
Transport: internal.GetHTTPTransport(a.registry.Insecure),
Transport: tr,
},
}
if a.forceEndpoint != nil {

View File

@ -18,18 +18,19 @@ import (
"encoding/base64"
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
awsecrapi "github.com/aws/aws-sdk-go/service/ecr"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/http/modifier"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/internal"
"net/http"
"net/url"
"strings"
"time"
)
// Credential ...
@ -96,11 +97,18 @@ func (a *awsAuthCredential) getAuthorization() (string, string, string, *time.Ti
a.accessKey,
a.accessSecret,
"")
var tr *http.Transport
if a.insecure {
tr = commonhttp.GetHTTPTransport(commonhttp.InsecureTransport)
} else {
tr = commonhttp.GetHTTPTransport(commonhttp.SecureTransport)
}
config := &aws.Config{
Credentials: cred,
Region: &a.region,
HTTPClient: &http.Client{
Transport: internal.GetHTTPTransport(a.insecure),
Transport: tr,
},
}
if a.forceEndpoint != nil {

View File

@ -26,7 +26,9 @@ import (
"github.com/goharbor/harbor/src/common/http/modifier"
common_http_auth "github.com/goharbor/harbor/src/common/http/modifier/auth"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/jobservice/config"
"github.com/goharbor/harbor/src/pkg/registry/auth/basic"
adp "github.com/goharbor/harbor/src/replication/adapter"
"github.com/goharbor/harbor/src/replication/adapter/native"
"github.com/goharbor/harbor/src/replication/model"
@ -68,7 +70,12 @@ type adapter struct {
}
func newAdapter(registry *model.Registry) (*adapter, error) {
transport := util.GetHTTPTransport(registry.Insecure)
var transport *http.Transport
if registry.URL == config.GetCoreURL() {
transport = common_http.GetHTTPTransport(common_http.SecureTransport)
} else {
transport = util.GetHTTPTransport(registry.Insecure)
}
// local Harbor instance
if registry.Credential != nil && registry.Credential.Type == model.CredentialTypeSecret {
authorizer := common_http_auth.NewSecretAuthorizer(registry.Credential.AccessSecret)
@ -296,6 +303,9 @@ func (a *adapter) getProject(name string) (*project, error) {
// when harbor is deployed on Kubernetes
func (a *adapter) getURL() string {
if a.registry.Type == model.RegistryTypeHarbor && a.registry.Name == "Local" {
if common_http.InternalTLSEnabled() {
return "https://core:8443"
}
return "http://127.0.0.1:8080"
}
return a.url

View File

@ -17,6 +17,7 @@ package native
import (
"errors"
"fmt"
"github.com/goharbor/harbor/src/common/utils"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/internal"

View File

@ -18,14 +18,14 @@ import (
"errors"
"fmt"
"github.com/goharbor/harbor/src/replication/util"
commonthttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/replication/config"
"github.com/goharbor/harbor/src/replication/model"
"github.com/goharbor/harbor/src/replication/operation"
"github.com/goharbor/harbor/src/replication/policy"
"github.com/goharbor/harbor/src/replication/registry"
"github.com/goharbor/harbor/src/replication/util"
)
// Handler is the handler to handle event
@ -191,6 +191,6 @@ func GetLocalRegistry() *model.Registry {
// use secret to do the auth for the local Harbor
AccessSecret: config.Config.JobserviceSecret,
},
Insecure: true,
Insecure: !commonthttp.InternalTLSEnabled(),
}
}

View File

@ -15,14 +15,18 @@
package util
import (
"github.com/goharbor/harbor/src/internal"
"net/http"
"strings"
commonhttp "github.com/goharbor/harbor/src/common/http"
)
// GetHTTPTransport can be used to share the common HTTP transport
func GetHTTPTransport(insecure bool) *http.Transport {
return internal.GetHTTPTransport(insecure)
if insecure {
return commonhttp.GetHTTPTransport(commonhttp.InsecureTransport)
}
return commonhttp.GetHTTPTransport(commonhttp.SecureTransport)
}
// ParseRepository parses the "repository" provided into two parts: namespace and the rest

View File

@ -16,10 +16,12 @@ package registry
import (
"fmt"
"github.com/goharbor/harbor/src/core/config"
"net/http"
"net/http/httputil"
"net/url"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/core/config"
)
var proxy = newProxy()
@ -31,6 +33,10 @@ func newProxy() http.Handler {
panic(fmt.Sprintf("failed to parse the URL of registry: %v", err))
}
proxy := httputil.NewSingleHostReverseProxy(url)
if commonhttp.InternalTLSEnabled() {
proxy.Transport = commonhttp.GetHTTPTransport(commonhttp.SecureTransport)
}
proxy.Director = basicAuthDirector(proxy.Director)
return proxy
}

View File

@ -30,5 +30,5 @@ if [ $GITHUB_TOKEN ];
then
sed "s/# github_token: xxx/github_token: $GITHUB_TOKEN/" -i make/harbor.yml
fi
sudo make install GOBUILDIMAGE=golang:1.13.4 COMPILETAG=compile_golangimage CLARITYIMAGE=goharbor/harbor-clarity-ui-builder:1.6.0 NOTARYFLAG=true CLAIRFLAG=true TRIVYFLAG=true CHARTFLAG=true
sudo make install GOBUILDIMAGE=golang:1.13.4 COMPILETAG=compile_golangimage CLARITYIMAGE=goharbor/harbor-clarity-ui-builder:1.6.0 NOTARYFLAG=true CLAIRFLAG=true TRIVYFLAG=true CHARTFLAG=true GEN_TLS=true
sleep 10

View File

@ -22,6 +22,7 @@ sudo -E env "PATH=$PATH" make go_check
sudo ./tests/hostcfg.sh
sudo ./tests/generateCerts.sh
sudo make -f make/photon/Makefile _build_db _build_registry _build_prepare -e VERSIONTAG=dev -e REGISTRYVERSION=${REG_VERSION} -e BASEIMAGETAG=dev
docker run --rm -v /:/hostfs:z goharbor/prepare:dev gencert -p /etc/harbor/tls/internal
sudo MAKEPATH=$(pwd)/make ./make/prepare
sudo mkdir -p "/data/redis"
sudo mkdir -p /etc/core/ca/ && sudo mv ./tests/ca.crt /etc/core/ca/

View File

@ -4,6 +4,12 @@ IP=`ip addr s eth0 |grep "inet "|awk '{print $2}' |awk -F "/" '{print $1}'`
#echo $IP
sudo sed "s/reg.mydomain.com/$IP/" make/harbor.yml.tmpl |sudo tee make/harbor.yml
# enable internal tls
echo "internal_tls:" >> make/harbor.yml
echo " enabled: true" >> make/harbor.yml
echo " verify_client_cert: true" >> make/harbor.yml
echo " dir: /etc/harbor/tls/internal" >> make/harbor.yml
# TODO: remove it when scanner adapter support internal access of harbor
echo "storage_service:" >> make/harbor.yml
echo " ca_bundle: /data/cert/server.crt" >> make/harbor.yml