mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 10:45:45 +01:00
Merge branch 'master' into fix_issues_for_jobservice
This commit is contained in:
commit
3937c8b0dc
2
Makefile
2
Makefile
@ -101,7 +101,7 @@ PREPARE_VERSION_NAME=versions
|
||||
REGISTRYVERSION=v2.7.1-patch-2819
|
||||
NGINXVERSION=$(VERSIONTAG)
|
||||
NOTARYVERSION=v0.6.1
|
||||
CLAIRVERSION=v2.0.7
|
||||
CLAIRVERSION=v2.0.8
|
||||
CLAIRDBVERSION=$(VERSIONTAG)
|
||||
MIGRATORVERSION=$(VERSIONTAG)
|
||||
REDISVERSION=$(VERSIONTAG)
|
||||
|
@ -940,6 +940,44 @@ paths:
|
||||
description: User ID does not exist.
|
||||
'500':
|
||||
description: Unexpected internal errors.
|
||||
'/users/{user_id}/gen_cli_secret':
|
||||
post:
|
||||
summary: Generate new CLI secret for a user.
|
||||
description: |
|
||||
This endpoint let user generate a new CLI secret for himself. This API only works when auth mode is set to 'OIDC'.
|
||||
Once this API returns with successful status, the old secret will be invalid, as there will be only one CLI secret
|
||||
for a user. The new secret will be returned in the response.
|
||||
parameters:
|
||||
- name: user_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int
|
||||
required: true
|
||||
description: User ID
|
||||
tags:
|
||||
- Products
|
||||
responses:
|
||||
'200':
|
||||
description: The secret is successfully generated.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
secret:
|
||||
type: string
|
||||
description: The new secret
|
||||
'400':
|
||||
description: Invalid user ID. Or user is not onboarded via OIDC authentication.
|
||||
'401':
|
||||
description: User need to log in first.
|
||||
'403':
|
||||
description: Non-admin user can only generate the cli secret of himself.
|
||||
'404':
|
||||
description: User ID does not exist.
|
||||
'412':
|
||||
description: The auth mode of the system is not "oidc_auth", or the user is not onboarded via OIDC AuthN.
|
||||
'500':
|
||||
description: Unexpected internal errors.
|
||||
|
||||
/repositories:
|
||||
get:
|
||||
summary: Get repositories accompany with relevant project and repo name.
|
||||
@ -1884,14 +1922,14 @@ paths:
|
||||
description: |
|
||||
Delete the replication policy specified by ID.
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Replication policy ID
|
||||
- name: id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Replication policy ID
|
||||
tags:
|
||||
- Products
|
||||
- Products
|
||||
responses:
|
||||
'200':
|
||||
$ref: '#/responses/OK'
|
||||
@ -2297,18 +2335,18 @@ paths:
|
||||
description: |
|
||||
This endpoint let user list namespaces of registry according to query.
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
type: integer
|
||||
required: true
|
||||
description: The registry ID.
|
||||
- name: name
|
||||
in: query
|
||||
type: string
|
||||
required: false
|
||||
description: The name of namespace.
|
||||
- name: id
|
||||
in: path
|
||||
type: integer
|
||||
required: true
|
||||
description: The registry ID.
|
||||
- name: name
|
||||
in: query
|
||||
type: string
|
||||
required: false
|
||||
description: The name of namespace.
|
||||
tags:
|
||||
- Products
|
||||
- Products
|
||||
responses:
|
||||
'200':
|
||||
description: Success
|
||||
@ -2661,7 +2699,7 @@ paths:
|
||||
'200':
|
||||
description: Get gc results successfully.
|
||||
schema:
|
||||
$ref: '#/definitions/GCResult'
|
||||
$ref: '#/definitions/GCResult'
|
||||
'401':
|
||||
description: User need to log in first.
|
||||
'403':
|
||||
@ -2706,7 +2744,7 @@ paths:
|
||||
'200':
|
||||
description: Get gc's schedule.
|
||||
schema:
|
||||
$ref: '#/definitions/AdminJobSchedule'
|
||||
$ref: '#/definitions/AdminJobSchedule'
|
||||
'401':
|
||||
description: User need to log in first.
|
||||
'403':
|
||||
@ -2768,12 +2806,12 @@ paths:
|
||||
summary: Get scan_all's schedule.
|
||||
description: This endpoint is for getting a schedule for the scan all job, which scans all of images in Harbor.
|
||||
tags:
|
||||
- Products
|
||||
- Products
|
||||
responses:
|
||||
'200':
|
||||
description: Get a schedule for the scan all job, which scans all of images in Harbor.
|
||||
schema:
|
||||
$ref: '#/definitions/AdminJobSchedule'
|
||||
$ref: '#/definitions/AdminJobSchedule'
|
||||
'401':
|
||||
description: User need to log in first.
|
||||
'403':
|
||||
@ -2785,14 +2823,14 @@ paths:
|
||||
description: |
|
||||
This endpoint is for updating the schedule of scan all job, which scans all of images in Harbor.
|
||||
parameters:
|
||||
- name: schedule
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/AdminJobSchedule'
|
||||
description: Updates the schedule of scan all job, which scans all of images in Harbor.
|
||||
- name: schedule
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/AdminJobSchedule'
|
||||
description: Updates the schedule of scan all job, which scans all of images in Harbor.
|
||||
tags:
|
||||
- Products
|
||||
- Products
|
||||
responses:
|
||||
'200':
|
||||
description: Updated scan_all's schedule successfully.
|
||||
@ -2809,14 +2847,14 @@ paths:
|
||||
description: |
|
||||
This endpoint is for creating a schedule or a manual trigger for the scan all job, which scans all of images in Harbor.
|
||||
parameters:
|
||||
- name: schedule
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/AdminJobSchedule'
|
||||
description: Create a schedule or a manual trigger for the scan all job.
|
||||
- name: schedule
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/AdminJobSchedule'
|
||||
description: Create a schedule or a manual trigger for the scan all job.
|
||||
tags:
|
||||
- Products
|
||||
- Products
|
||||
responses:
|
||||
'200':
|
||||
description: Updated scan_all's schedule successfully.
|
||||
@ -3289,15 +3327,15 @@ paths:
|
||||
summary: Get all robot accounts of specified project
|
||||
description: Get all robot accounts of specified project
|
||||
parameters:
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
tags:
|
||||
- Products
|
||||
- Robot Account
|
||||
- Products
|
||||
- Robot Account
|
||||
responses:
|
||||
'200':
|
||||
description: Get project robot accounts successfully.
|
||||
@ -3319,21 +3357,21 @@ paths:
|
||||
summary: Create a robot account for project
|
||||
description: Create a robot account for project
|
||||
tags:
|
||||
- Products
|
||||
- Robot Account
|
||||
- Products
|
||||
- Robot Account
|
||||
parameters:
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
- name: robot
|
||||
in: body
|
||||
description: Request body of creating a robot account.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/RobotAccountCreate'
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
- name: robot
|
||||
in: body
|
||||
description: Request body of creating a robot account.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/RobotAccountCreate'
|
||||
responses:
|
||||
'201':
|
||||
description: Project member created successfully.
|
||||
@ -3354,21 +3392,21 @@ paths:
|
||||
summary: Return the infor of the specified robot account.
|
||||
description: Return the infor of the specified robot account.
|
||||
tags:
|
||||
- Products
|
||||
- Robot Account
|
||||
- Products
|
||||
- Robot Account
|
||||
parameters:
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
- name: robot_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: The ID of robot account.
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
- name: robot_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: The ID of robot account.
|
||||
responses:
|
||||
'200':
|
||||
description: Robot account information.
|
||||
@ -3386,27 +3424,27 @@ paths:
|
||||
summary: Update status of robot account.
|
||||
description: Used to disable/enable a specified robot account.
|
||||
tags:
|
||||
- Products
|
||||
- Robot Account
|
||||
- Products
|
||||
- Robot Account
|
||||
parameters:
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
- name: robot_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: The ID of robot account.
|
||||
- name: robot
|
||||
in: body
|
||||
description: Request body of enable/disable a robot account.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/RobotAccountUpdate'
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
- name: robot_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: The ID of robot account.
|
||||
- name: robot
|
||||
in: body
|
||||
description: Request body of enable/disable a robot account.
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/RobotAccountUpdate'
|
||||
responses:
|
||||
'200':
|
||||
description: Robot account has been modified success.
|
||||
@ -3416,21 +3454,21 @@ paths:
|
||||
summary: Delete the specified robot account
|
||||
description: Delete the specified robot account
|
||||
tags:
|
||||
- Products
|
||||
- Robot Account
|
||||
- Products
|
||||
- Robot Account
|
||||
parameters:
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
- name: robot_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: The ID of robot account.
|
||||
- name: project_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: Relevant project ID.
|
||||
- name: robot_id
|
||||
in: path
|
||||
type: integer
|
||||
format: int64
|
||||
required: true
|
||||
description: The ID of robot account.
|
||||
responses:
|
||||
'200':
|
||||
description: The specified robot account is successfully deleted.
|
||||
|
@ -3,15 +3,19 @@
|
||||
#The IP address or hostname to access admin UI and registry service.
|
||||
#DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
|
||||
hostname: reg.mydomain.com
|
||||
# core, harbor
|
||||
|
||||
# http related comfig
|
||||
http:
|
||||
# port for http, default is 80. If https enabled, this port will redirect to https port
|
||||
port: 80
|
||||
|
||||
# https:
|
||||
# port: 443
|
||||
# #The path of cert and key files for nginx
|
||||
# certificate: /your/certificate/path
|
||||
# private_key: /your/private/key/path
|
||||
# https related comfig
|
||||
https:
|
||||
# https port for harbor, default is 443
|
||||
port: 443
|
||||
#The path of cert and key files for nginx
|
||||
certificate: /data/cert/server.crt
|
||||
private_key: /data/cert/server.key
|
||||
|
||||
# Uncomment extearnal_url if you want to enable external proxy
|
||||
# And when it enabled the hostname will no longger used
|
||||
|
@ -38,7 +38,7 @@ CREATE TABLE oidc_user (
|
||||
UNIQUE (subiss)
|
||||
);
|
||||
|
||||
CREATE TRIGGER odic_user_update_time_at_modtime BEFORE UPDATE ON oidc_user FOR EACH ROW EXECUTE PROCEDURE update_update_time_at_column();
|
||||
CREATE TRIGGER oidc_user_update_time_at_modtime BEFORE UPDATE ON oidc_user FOR EACH ROW EXECUTE PROCEDURE update_update_time_at_column();
|
||||
|
||||
/*add master role*/
|
||||
INSERT INTO role (role_code, name) VALUES ('DRWS', 'master');
|
||||
|
@ -6,7 +6,7 @@ name = "pypi"
|
||||
[packages]
|
||||
pyyaml = "==4.2b1"
|
||||
click = "*"
|
||||
"jinja2" = "*"
|
||||
"jinja2" = ">=2.10.1"
|
||||
|
||||
[dev-packages]
|
||||
pylint = "*"
|
||||
|
55
make/photon/prepare/Pipfile.lock
generated
55
make/photon/prepare/Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "0fd59e52429cbbc5e345259707a98d7c071a0a59ca709882d8b106321fb2191e"
|
||||
"sha256": "a3c7e13ece64f4447d0bd3648257ca4117192e5d52ff7cdd4b4c2d3109ae6500"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@ -26,11 +26,11 @@
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
|
||||
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
|
||||
"sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
|
||||
"sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.10"
|
||||
"version": "==2.10.1"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
@ -83,10 +83,10 @@
|
||||
},
|
||||
"isort": {
|
||||
"hashes": [
|
||||
"sha256:18c796c2cd35eb1a1d3f012a214a542790a1aed95e29768bdcb9f2197eccbd0b",
|
||||
"sha256:96151fca2c6e736503981896495d344781b60d18bfda78dc11b290c6125ebdb6"
|
||||
"sha256:01cb7e1ca5e6c5b3f235f0385057f70558b70d2f00320208825fa62887292f43",
|
||||
"sha256:268067462aed7eb2a1e237fcb287852f22077de3fb07964e87e00f829eea2d1a"
|
||||
],
|
||||
"version": "==4.3.15"
|
||||
"version": "==4.3.17"
|
||||
},
|
||||
"lazy-object-proxy": {
|
||||
"hashes": [
|
||||
@ -146,28 +146,29 @@
|
||||
},
|
||||
"typed-ast": {
|
||||
"hashes": [
|
||||
"sha256:035a54ede6ce1380599b2ce57844c6554666522e376bd111eb940fbc7c3dad23",
|
||||
"sha256:037c35f2741ce3a9ac0d55abfcd119133cbd821fffa4461397718287092d9d15",
|
||||
"sha256:049feae7e9f180b64efacbdc36b3af64a00393a47be22fa9cb6794e68d4e73d3",
|
||||
"sha256:19228f7940beafc1ba21a6e8e070e0b0bfd1457902a3a81709762b8b9039b88d",
|
||||
"sha256:2ea681e91e3550a30c2265d2916f40a5f5d89b59469a20f3bad7d07adee0f7a6",
|
||||
"sha256:3a6b0a78af298d82323660df5497bcea0f0a4a25a0b003afd0ce5af049bd1f60",
|
||||
"sha256:5385da8f3b801014504df0852bf83524599df890387a3c2b17b7caa3d78b1773",
|
||||
"sha256:606d8afa07eef77280c2bf84335e24390055b478392e1975f96286d99d0cb424",
|
||||
"sha256:69245b5b23bbf7fb242c9f8f08493e9ecd7711f063259aefffaeb90595d62287",
|
||||
"sha256:6f6d839ab09830d59b7fa8fb6917023d8cb5498ee1f1dbd82d37db78eb76bc99",
|
||||
"sha256:730888475f5ac0e37c1de4bd05eeb799fdb742697867f524dc8a4cd74bcecc23",
|
||||
"sha256:9819b5162ffc121b9e334923c685b0d0826154e41dfe70b2ede2ce29034c71d8",
|
||||
"sha256:9e60ef9426efab601dd9aa120e4ff560f4461cf8442e9c0a2b92548d52800699",
|
||||
"sha256:af5fbdde0690c7da68e841d7fc2632345d570768ea7406a9434446d7b33b0ee1",
|
||||
"sha256:b64efdbdf3bbb1377562c179f167f3bf301251411eb5ac77dec6b7d32bcda463",
|
||||
"sha256:bac5f444c118aeb456fac1b0b5d14c6a71ea2a42069b09c176f75e9bd4c186f6",
|
||||
"sha256:bda9068aafb73859491e13b99b682bd299c1b5fd50644d697533775828a28ee0",
|
||||
"sha256:d659517ca116e6750101a1326107d3479028c5191f0ecee3c7203c50f5b915b0",
|
||||
"sha256:eddd3fb1f3e0f82e5915a899285a39ee34ce18fd25d89582bc89fc9fb16cd2c6"
|
||||
"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"
|
||||
],
|
||||
"markers": "implementation_name == 'cpython'",
|
||||
"version": "==1.3.1"
|
||||
"version": "==1.3.4"
|
||||
},
|
||||
"wrapt": {
|
||||
"hashes": [
|
||||
|
@ -92,10 +92,17 @@ func GetOIDCUserByUserID(userID int) (*models.OIDCUser, error) {
|
||||
return &oidcUsers[0], nil
|
||||
}
|
||||
|
||||
// UpdateOIDCUser ...
|
||||
// UpdateOIDCUser updates the OIDCUser based on the input parm, only the column "secret" and "token" can be updated
|
||||
func UpdateOIDCUser(oidcUser *models.OIDCUser) error {
|
||||
oidcUser.UpdateTime = time.Now()
|
||||
_, err := GetOrmer().Update(oidcUser)
|
||||
cols := []string{"secret", "token"}
|
||||
_, err := GetOrmer().Update(oidcUser, cols...)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateOIDCUserSecret updates the secret of the OIDC User. The secret in the input parm should be encrypted before
|
||||
// calling this func
|
||||
func UpdateOIDCUserSecret(oidcUser *models.OIDCUser) error {
|
||||
_, err := GetOrmer().Update(oidcUser, "secret")
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -80,15 +80,13 @@ func TestOIDCUserMetaDaoMethods(t *testing.T) {
|
||||
ID: ou111.ID,
|
||||
UserID: ou111.UserID,
|
||||
SubIss: "newSub",
|
||||
Secret: "newSecret",
|
||||
}
|
||||
require.Nil(t, UpdateOIDCUser(meta3))
|
||||
oidcUser1Update, err := GetOIDCUserByID(ou111.ID)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "newSub", oidcUser1Update.SubIss)
|
||||
|
||||
user, err := GetUserBySubIss("new", "Sub")
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "user111", user.Username)
|
||||
assert.Equal(t, "QWE123123RT1", oidcUser1Update.SubIss)
|
||||
assert.Equal(t, "newSecret", oidcUser1Update.Secret)
|
||||
|
||||
// clear data
|
||||
defer func() {
|
||||
|
@ -38,6 +38,7 @@ type UserAPI struct {
|
||||
SelfRegistration bool
|
||||
IsAdmin bool
|
||||
AuthMode string
|
||||
secretKey string
|
||||
}
|
||||
|
||||
type passwordReq struct {
|
||||
@ -50,6 +51,10 @@ type userSearch struct {
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
type secretResp struct {
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
// Prepare validates the URL and parms
|
||||
func (ua *UserAPI) Prepare() {
|
||||
ua.BaseController.Prepare()
|
||||
@ -61,6 +66,15 @@ func (ua *UserAPI) Prepare() {
|
||||
}
|
||||
|
||||
ua.AuthMode = mode
|
||||
if mode == common.OIDCAuth {
|
||||
key, err := config.SecretKey()
|
||||
if err != nil {
|
||||
log.Errorf("failed to get secret key: %v", err)
|
||||
ua.SendInternalServerError(fmt.Errorf("failed to get secret key: %v", err))
|
||||
return
|
||||
}
|
||||
ua.secretKey = key
|
||||
}
|
||||
|
||||
self, err := config.SelfRegistration()
|
||||
if err != nil {
|
||||
@ -475,17 +489,53 @@ func (ua *UserAPI) ListUserPermissions() {
|
||||
return
|
||||
}
|
||||
|
||||
func (ua *UserAPI) getOIDCUserInfo() (*models.OIDCUser, error) {
|
||||
key, err := config.SecretKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// GenCLISecret generates a new CLI secret and replace the old one
|
||||
func (ua *UserAPI) GenCLISecret() {
|
||||
if ua.AuthMode != common.OIDCAuth {
|
||||
ua.SendPreconditionFailedError(errors.New("the auth mode has to be oidc auth"))
|
||||
return
|
||||
}
|
||||
if ua.userID != ua.currentUserID && !ua.IsAdmin {
|
||||
ua.SendForbiddenError(errors.New(""))
|
||||
return
|
||||
}
|
||||
oidcData, err := dao.GetOIDCUserByUserID(ua.userID)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get OIDC User meta for user, id: %d, error: %v", ua.userID, err)
|
||||
ua.SendInternalServerError(errors.New("failed to get OIDC meta data for user"))
|
||||
return
|
||||
}
|
||||
if oidcData == nil {
|
||||
log.Errorf("User is not onboarded via OIDC AuthN, user id: %d", ua.userID)
|
||||
ua.SendPreconditionFailedError(errors.New("user is not onboarded via OIDC AuthN"))
|
||||
return
|
||||
}
|
||||
|
||||
sec := utils.GenerateRandomString()
|
||||
encSec, err := utils.ReversibleEncrypt(sec, ua.secretKey)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to encrypt secret, error: %v", err)
|
||||
ua.SendInternalServerError(errors.New("failed to encrypt secret"))
|
||||
return
|
||||
}
|
||||
oidcData.Secret = encSec
|
||||
err = dao.UpdateOIDCUserSecret(oidcData)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to update secret in DB, error: %v", err)
|
||||
ua.SendInternalServerError(errors.New("failed to update secret in DB"))
|
||||
return
|
||||
}
|
||||
ua.Data["json"] = secretResp{sec}
|
||||
ua.ServeJSON()
|
||||
}
|
||||
|
||||
func (ua *UserAPI) getOIDCUserInfo() (*models.OIDCUser, error) {
|
||||
o, err := dao.GetOIDCUserByUserID(ua.userID)
|
||||
if err != nil || o == nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(o.Secret) > 0 {
|
||||
p, err := utils.ReversibleDecrypt(o.Secret, key)
|
||||
p, err := utils.ReversibleDecrypt(o.Secret, ua.secretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ func initRouters() {
|
||||
beego.Router("/api/users/:id([0-9]+)/password", &api.UserAPI{}, "put:ChangePassword")
|
||||
beego.Router("/api/users/:id/permissions", &api.UserAPI{}, "get:ListUserPermissions")
|
||||
beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole")
|
||||
beego.Router("/api/users/:id/gen_cli_secret", &api.UserAPI{}, "post:GenCLISecret")
|
||||
beego.Router("/api/usergroups/?:ugid([0-9]+)", &api.UserGroupAPI{})
|
||||
beego.Router("/api/ldap/ping", &api.LdapAPI{}, "post:Ping")
|
||||
beego.Router("/api/ldap/users/search", &api.LdapAPI{}, "get:Search")
|
||||
|
@ -15,8 +15,8 @@
|
||||
<div class="form-group">
|
||||
<label class="form-group-label-override required">{{'DESTINATION.PROVIDER' | translate}}</label>
|
||||
<div class="form-select">
|
||||
<div class="select providerSelect pull-left">
|
||||
<select name="adapter" id="adapter" [(ngModel)]="target.type" [disabled]="testOngoing || controlEnabled">
|
||||
<div class="select inputWidth pull-left">
|
||||
<select name="adapter" id="adapter" (change)="adapterChange($event)" [(ngModel)]="target.type" [disabled]="testOngoing || editDisabled">
|
||||
<option *ngFor="let adapter of adapterList" value="{{adapter}}">{{adapter}}</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -29,7 +29,7 @@
|
||||
<label class="col-md-8" for="destination_name" aria-haspopup="true" role="tooltip" [class.invalid]="targetName.errors && (targetName.dirty || targetName.touched)"
|
||||
[class.valid]="targetName.valid" class="tooltip tooltip-validation tooltip-sm tooltip-bottom-left">
|
||||
<input type="text" id="destination_name" [disabled]="testOngoing" [readonly]="!editable" [(ngModel)]="target.name"
|
||||
name="targetName" size="20" #targetName="ngModel" required>
|
||||
name="targetName" size="25" #targetName="ngModel" required>
|
||||
<span class="tooltip-content" *ngIf="targetName.errors && targetName.errors.required && (targetName.dirty || targetName.touched)">
|
||||
{{ 'DESTINATION.NAME_IS_REQUIRED' | translate }}
|
||||
</span>
|
||||
@ -46,8 +46,8 @@
|
||||
translate }}</label>
|
||||
<label class="col-md-8" for="destination_url" aria-haspopup="true" role="tooltip" [class.invalid]="targetEndpoint.errors && (targetEndpoint.dirty || targetEndpoint.touched)"
|
||||
[class.valid]="targetEndpoint.valid" class="tooltip tooltip-validation tooltip-sm tooltip-bottom-left">
|
||||
<input type="text" id="destination_url" [disabled]="testOngoing || controlEnabled" [readonly]="!editable" [(ngModel)]="target.url"
|
||||
size="20" name="endpointUrl" #targetEndpoint="ngModel" required placeholder="http(s)://192.168.1.1">
|
||||
<input type="text" id="destination_url" [disabled]="testOngoing || editDisabled || controlEnabled" [readonly]="!editable" [(ngModel)]="target.url"
|
||||
size="25" name="endpointUrl" #targetEndpoint="ngModel" required placeholder="http(s)://192.168.1.1">
|
||||
<span class="tooltip-content" *ngIf="targetEndpoint.errors && targetEndpoint.errors.required && (targetEndpoint.dirty || targetEndpoint.touched)">
|
||||
{{ 'DESTINATION.URL_IS_REQUIRED' | translate }}
|
||||
</span>
|
||||
@ -58,14 +58,14 @@
|
||||
<label for="destination_access_key" class="col-md-4 form-group-label-override">{{ 'DESTINATION.ACCESS_ID' |
|
||||
translate }}</label>
|
||||
<input type="text" placeholder="Access ID" class="col-md-8" id="destination_access_key" [disabled]="testOngoing" [readonly]="!editable"
|
||||
[(ngModel)]="target.credential.access_key" size="23" name="access_key" #access_key="ngModel">
|
||||
[(ngModel)]="target.credential.access_key" size="28" name="access_key" #access_key="ngModel">
|
||||
</div>
|
||||
<!-- access_secret -->
|
||||
<div class="form-group">
|
||||
<label for="destination_password" class="col-md-4 form-group-label-override">{{ 'DESTINATION.ACCESS_SECRET' |
|
||||
translate }}</label>
|
||||
<input type="password" placeholder="Access Secret" class="col-md-8" id="destination_password" [disabled]="testOngoing" [readonly]="!editable"
|
||||
[(ngModel)]="target.credential.access_secret" size="23" name="access_secret" #access_secret="ngModel">
|
||||
[(ngModel)]="target.credential.access_secret" size="28" name="access_secret" #access_secret="ngModel">
|
||||
</div>
|
||||
<!-- Verify Remote Cert -->
|
||||
<div class="form-group">
|
||||
|
@ -12,10 +12,6 @@
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.providerSelect {
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.inputWidth {
|
||||
width: 182px;
|
||||
width: 216px;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import { Endpoint } from "../service/interface";
|
||||
import { clone, compareValue, isEmptyObject } from "../utils";
|
||||
|
||||
const FAKE_PASSWORD = "rjGcfuRu";
|
||||
|
||||
const DOCKERHUB_URL = "https://registry-1.docker.io";
|
||||
@Component({
|
||||
selector: "hbr-create-edit-endpoint",
|
||||
templateUrl: "./create-edit-endpoint.component.html",
|
||||
@ -41,6 +41,7 @@ const FAKE_PASSWORD = "rjGcfuRu";
|
||||
export class CreateEditEndpointComponent
|
||||
implements AfterViewChecked, OnDestroy, OnInit {
|
||||
modalTitle: string;
|
||||
editDisabled: boolean = false;
|
||||
controlEnabled: boolean = false;
|
||||
createEditDestinationOpened: boolean;
|
||||
staticBackdrop: boolean = true;
|
||||
@ -178,7 +179,7 @@ export class CreateEditEndpointComponent
|
||||
|
||||
// Open the modal now
|
||||
this.open();
|
||||
this.controlEnabled = true;
|
||||
this.editDisabled = true;
|
||||
this.forceRefreshView(2000);
|
||||
},
|
||||
error => this.errorHandler.error(error)
|
||||
@ -190,6 +191,17 @@ export class CreateEditEndpointComponent
|
||||
.subscribe(res => (this.modalTitle = res));
|
||||
// Directly open the modal
|
||||
this.open();
|
||||
this.editDisabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
adapterChange($event): void {
|
||||
let selectValue = this.targetForm.controls.adapter.value;
|
||||
if (selectValue === 'dockerHub') {
|
||||
this.targetForm.controls.endpointUrl.setValue(DOCKERHUB_URL);
|
||||
this.controlEnabled = true;
|
||||
} else {
|
||||
this.targetForm.controls.endpointUrl.setValue("");
|
||||
this.controlEnabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -474,9 +474,7 @@ export class ReplicationComponent implements OnInit, OnDestroy {
|
||||
if (!j) {
|
||||
return;
|
||||
}
|
||||
if (j.status === "Failed") {
|
||||
return "-";
|
||||
}
|
||||
|
||||
let start_time = new Date(j.start_time).getTime();
|
||||
let end_time = new Date(j.end_time).getTime();
|
||||
let timesDiff = end_time - start_time;
|
||||
|
@ -3,7 +3,3 @@ IP=`ip addr s eth0 |grep "inet "|awk '{print $2}' |awk -F "/" '{print $1}'`
|
||||
|
||||
#echo $IP
|
||||
sudo sed "s/reg.mydomain.com/$IP/" -i make/harbor.yml
|
||||
|
||||
echo "https:" >> make/harbor.yml
|
||||
echo " certificate: /data/cert/server.crt" >> make/harbor.yml
|
||||
echo " private_key: /data/cert/server.key" >> make/harbor.yml
|
@ -18,22 +18,18 @@ Resource ../../resources/Util.robot
|
||||
|
||||
*** Keywords ***
|
||||
View Repo Scan Details
|
||||
Click Element xpath=${first_repo_xpath}
|
||||
Sleep 2
|
||||
Retry Element Click xpath=${first_repo_xpath}
|
||||
Capture Page Screenshot viewcve1.png
|
||||
Wait Until Page Contains unknown
|
||||
Wait Until Page Contains high
|
||||
Wait Until Page Contains medium
|
||||
Page Should Contain CVE
|
||||
Sleep 2
|
||||
Click Element xpath=${build_history_btn}
|
||||
Sleep 1
|
||||
Page Should Contain Element xpath=${build_history_data}
|
||||
Retry Wait Until Page Contains unknown
|
||||
Retry Wait Until Page Contains high
|
||||
Retry Wait Until Page Contains medium
|
||||
Retry Wait Until Page Contains CVE
|
||||
Retry Element Click xpath=${build_history_btn}
|
||||
Retry Wait Until Page Contains Element xpath=${build_history_data}
|
||||
|
||||
View Scan Error Log
|
||||
Page Should Contain View Log
|
||||
Click Element xpath=${view_log_xpath}
|
||||
Sleep 1
|
||||
Retry Wait Until Page Contains View Log
|
||||
Retry Element Click xpath=${view_log_xpath}
|
||||
Capture Page Screenshot viewlog.png
|
||||
|
||||
|
||||
|
@ -21,11 +21,11 @@ ${HARBOR_VERSION} v1.1.1
|
||||
|
||||
*** Keywords ***
|
||||
Check New Rule UI Without Endpoint
|
||||
Click Element ${new_replication-rule_button}
|
||||
Page Should Contain Please add an endpoint first
|
||||
Mouse Down ${link_to_registries}
|
||||
Mouse Up ${link_to_registries}
|
||||
Page Should Contain Endpoint Name
|
||||
Retry Element Click ${new_replication-rule_button}
|
||||
Page Should Contain Please add an endpoint first
|
||||
Retry Element Click ${link_to_registries}
|
||||
Retry Wait Until Page Contains Endpoint URL
|
||||
Retry Wait Element ${new_endpoint_button}
|
||||
|
||||
Create A New Endpoint
|
||||
[Arguments] ${name} ${url} ${username} ${pwd} ${save}=Y
|
||||
|
@ -31,7 +31,7 @@ ${destination_insecure_xpath} //label[@id='destination_insecure_checkbox']
|
||||
|
||||
${new_replication-rule_button} //button[contains(.,'New Replication Rule')]
|
||||
${link_to_registries} //clr-modal//span[contains(.,'Endpoint')]
|
||||
${new_endpoint_button} //hbr-endpoint//button[contains(.,'New')]
|
||||
${new_endpoint_button} //hbr-endpoint//button[contains(.,'New Endpoint')]
|
||||
${rule_name} //input[@id='ruleName']
|
||||
${source_project} //input[@value='name']
|
||||
${source_image_filter_add} //hbr-create-edit-rule/clr-modal//clr-icon[@id='add-label-list']
|
||||
|
@ -34,3 +34,10 @@ ${REMOTE_SERVER_API_ENDPOINT} ${REMOTE_SERVER_URL}/api
|
||||
Test Case - Get Harbor Version
|
||||
#Just get harbor version and log it
|
||||
Get Harbor Version
|
||||
|
||||
Test Case - Pro Replication Rules Add
|
||||
Init Chrome Driver
|
||||
Sign In Harbor ${HARBOR_URL} ${HARBOR_ADMIN} ${HARBOR_PASSWORD}
|
||||
Switch To Replication Manage
|
||||
Check New Rule UI Without Endpoint
|
||||
Close Browser
|
||||
|
Loading…
Reference in New Issue
Block a user