mirror of https://github.com/goharbor/harbor.git
Move certificate verification to target level
The certificate verification is on system level before this commit. Moving it to target level makes the configuration more flexible for different targets.
This commit is contained in:
parent
75af80b4e8
commit
2156750b04
|
@ -2339,6 +2339,9 @@ definitions:
|
|||
type: integer
|
||||
format: int
|
||||
description: Reserved field.
|
||||
insecure:
|
||||
type: boolean
|
||||
description: Whether or not the certificate will be verified when Harbor tries to access the server.
|
||||
creation_time:
|
||||
type: string
|
||||
description: The create time of the policy.
|
||||
|
@ -2360,6 +2363,9 @@ definitions:
|
|||
password:
|
||||
type: string
|
||||
description: The target server password.
|
||||
insecure:
|
||||
type: boolean
|
||||
description: Whether or not the certificate will be verified when Harbor tries to access the server.
|
||||
PingTarget:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -2372,6 +2378,9 @@ definitions:
|
|||
password:
|
||||
type: string
|
||||
description: The target server password.
|
||||
insecure:
|
||||
type: boolean
|
||||
description: Whether or not the certificate will be verified when Harbor tries to access the server.
|
||||
PutTarget:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -2387,6 +2396,9 @@ definitions:
|
|||
password:
|
||||
type: string
|
||||
description: The target server password.
|
||||
insecure:
|
||||
type: boolean
|
||||
description: Whether or not the certificate will be verified when Harbor tries to access the server.
|
||||
HasAdminRole:
|
||||
type: object
|
||||
properties:
|
||||
|
|
|
@ -163,6 +163,7 @@ create table replication_target (
|
|||
1 means it's a regulart registry
|
||||
*/
|
||||
target_type tinyint(1) NOT NULL DEFAULT 0,
|
||||
insecure tinyint(1) NOT NULL DEFAULT 0,
|
||||
creation_time timestamp default CURRENT_TIMESTAMP,
|
||||
update_time timestamp default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id)
|
||||
|
|
|
@ -158,6 +158,7 @@ create table replication_target (
|
|||
1 means it's a regulart registry
|
||||
*/
|
||||
target_type tinyint(1) NOT NULL DEFAULT 0,
|
||||
insecure tinyint(1) NOT NULL DEFAULT 0,
|
||||
creation_time timestamp default CURRENT_TIMESTAMP,
|
||||
update_time timestamp default CURRENT_TIMESTAMP
|
||||
);
|
||||
|
|
|
@ -27,7 +27,6 @@ EMAIL_FROM=$email_from
|
|||
EMAIL_IDENTITY=$email_identity
|
||||
HARBOR_ADMIN_PASSWORD=$harbor_admin_password
|
||||
PROJECT_CREATION_RESTRICTION=$project_creation_restriction
|
||||
VERIFY_REMOTE_CERT=$verify_remote_cert
|
||||
MAX_JOB_WORKERS=$max_job_workers
|
||||
UI_SECRET=$ui_secret
|
||||
JOBSERVICE_SECRET=$jobservice_secret
|
||||
|
|
|
@ -149,7 +149,6 @@ if protocol == "https":
|
|||
customize_crt = rcp.get("configuration", "customize_crt")
|
||||
max_job_workers = rcp.get("configuration", "max_job_workers")
|
||||
token_expiration = rcp.get("configuration", "token_expiration")
|
||||
verify_remote_cert = rcp.get("configuration", "verify_remote_cert")
|
||||
proj_cre_restriction = rcp.get("configuration", "project_creation_restriction")
|
||||
secretkey_path = rcp.get("configuration", "secretkey_path")
|
||||
if rcp.has_option("configuration", "admiral_url"):
|
||||
|
@ -239,7 +238,6 @@ render(os.path.join(templates_dir, "adminserver", "env"),
|
|||
email_identity=email_identity,
|
||||
harbor_admin_password=harbor_admin_password,
|
||||
project_creation_restriction=proj_cre_restriction,
|
||||
verify_remote_cert=verify_remote_cert,
|
||||
max_job_workers=max_job_workers,
|
||||
ui_secret=ui_secret,
|
||||
jobservice_secret=jobservice_secret,
|
||||
|
|
|
@ -111,10 +111,6 @@ var (
|
|||
env: "MAX_JOB_WORKERS",
|
||||
parse: parseStringToInt,
|
||||
},
|
||||
common.VerifyRemoteCert: &parser{
|
||||
env: "VERIFY_REMOTE_CERT",
|
||||
parse: parseStringToBool,
|
||||
},
|
||||
common.ProjectCreationRestriction: "PROJECT_CREATION_RESTRICTION",
|
||||
common.AdminInitialPassword: "HARBOR_ADMIN_PASSWORD",
|
||||
common.AdmiralEndpoint: "ADMIRAL_URL",
|
||||
|
|
|
@ -57,7 +57,6 @@ const (
|
|||
EmailIdentity = "email_identity"
|
||||
EmailInsecure = "email_insecure"
|
||||
ProjectCreationRestriction = "project_creation_restriction"
|
||||
VerifyRemoteCert = "verify_remote_cert"
|
||||
MaxJobWorkers = "max_job_workers"
|
||||
TokenExpiration = "token_expiration"
|
||||
CfgExpiration = "cfg_expiration"
|
||||
|
|
|
@ -76,7 +76,7 @@ func DeleteRepTarget(id int64) error {
|
|||
func UpdateRepTarget(target models.RepTarget) error {
|
||||
o := GetOrmer()
|
||||
target.UpdateTime = time.Now()
|
||||
_, err := o.Update(&target, "URL", "Name", "Username", "Password", "UpdateTime")
|
||||
_, err := o.Update(&target, "URL", "Name", "Username", "Password", "Insecure", "UpdateTime")
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ type RepTarget struct {
|
|||
Username string `orm:"column(username)" json:"username"`
|
||||
Password string `orm:"column(password)" json:"password"`
|
||||
Type int `orm:"column(target_type)" json:"type"`
|
||||
Insecure bool `orm:"column(insecure)" json:"insecure"`
|
||||
CreationTime time.Time `orm:"column(creation_time);auto_now_add" json:"creation_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time);auto_now" json:"update_time"`
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ var adminServerDefaultConfig = map[string]interface{}{
|
|||
common.EmailInsecure: false,
|
||||
common.EmailIdentity: "",
|
||||
common.ProjectCreationRestriction: common.ProCrtRestrAdmOnly,
|
||||
common.VerifyRemoteCert: false,
|
||||
common.MaxJobWorkers: 3,
|
||||
common.TokenExpiration: 30,
|
||||
common.CfgExpiration: 5,
|
||||
|
|
|
@ -74,15 +74,6 @@ func initKeyProvider() {
|
|||
keyProvider = comcfg.NewFileKeyProvider(path)
|
||||
}
|
||||
|
||||
// VerifyRemoteCert returns bool value.
|
||||
func VerifyRemoteCert() (bool, error) {
|
||||
cfg, err := mg.Get()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return cfg[common.VerifyRemoteCert].(bool), nil
|
||||
}
|
||||
|
||||
// Database ...
|
||||
func Database() (*models.Database, error) {
|
||||
cfg, err := mg.Get()
|
||||
|
|
|
@ -49,10 +49,6 @@ func TestConfig(t *testing.T) {
|
|||
t.Fatalf("failed to initialize configurations: %v", err)
|
||||
}
|
||||
|
||||
if _, err := VerifyRemoteCert(); err != nil {
|
||||
t.Fatalf("failed to get verify remote cert: %v", err)
|
||||
}
|
||||
|
||||
if _, err := Database(); err != nil {
|
||||
t.Fatalf("failed to get database settings: %v", err)
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ func TestRepJob(t *testing.T) {
|
|||
j, err := dao.GetRepJob(repJobID)
|
||||
assert.Equal(models.JobRetrying, j.Status)
|
||||
assert.Equal(1, rj.parm.Enabled)
|
||||
assert.True(rj.parm.Insecure)
|
||||
assert.False(rj.parm.Insecure)
|
||||
rj2 := NewRepJob(99999)
|
||||
err = rj2.Init()
|
||||
assert.NotNil(err)
|
||||
|
|
|
@ -120,17 +120,12 @@ func (rj *RepJob) Init() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
verify, err := config.VerifyRemoteCert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rj.parm = &RepJobParm{
|
||||
LocalRegURL: regURL,
|
||||
Repository: job.Repository,
|
||||
Tags: job.TagList,
|
||||
Enabled: policy.Enabled,
|
||||
Operation: job.Operation,
|
||||
Insecure: !verify,
|
||||
}
|
||||
if policy.Enabled == 0 {
|
||||
//worker will cancel this job
|
||||
|
@ -159,6 +154,7 @@ func (rj *RepJob) Init() error {
|
|||
}
|
||||
|
||||
rj.parm.TargetPassword = pwd
|
||||
rj.parm.Insecure = target.Insecure
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ var (
|
|||
common.EmailIdentity,
|
||||
common.EmailInsecure,
|
||||
common.ProjectCreationRestriction,
|
||||
common.VerifyRemoteCert,
|
||||
common.TokenExpiration,
|
||||
common.ScanAllPolicy,
|
||||
}
|
||||
|
@ -81,7 +80,6 @@ var (
|
|||
common.EmailSSL,
|
||||
common.EmailInsecure,
|
||||
common.SelfRegistration,
|
||||
common.VerifyRemoteCert,
|
||||
}
|
||||
|
||||
passwordKeys = []string{
|
||||
|
|
|
@ -61,7 +61,7 @@ func TestPutConfig(t *testing.T) {
|
|||
apiTest := newHarborAPI()
|
||||
|
||||
cfg := map[string]interface{}{
|
||||
common.VerifyRemoteCert: false,
|
||||
common.TokenExpiration: 60,
|
||||
}
|
||||
|
||||
code, err := apiTest.PutConfig(*admin, cfg)
|
||||
|
@ -104,13 +104,13 @@ func TestResetConfig(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
value, ok := cfgs[common.VerifyRemoteCert]
|
||||
value, ok := cfgs[common.TokenExpiration]
|
||||
if !ok {
|
||||
t.Errorf("%s not found", common.VerifyRemoteCert)
|
||||
t.Errorf("%s not found", common.TokenExpiration)
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(value.Value.(bool), true, "unexpected value")
|
||||
assert.Equal(int(value.Value.(float64)), 30, "unexpected 30")
|
||||
|
||||
ccc, err := config.GetSystemCfg()
|
||||
if err != nil {
|
||||
|
|
|
@ -58,13 +58,8 @@ func (t *TargetAPI) Prepare() {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *TargetAPI) ping(endpoint, username, password string) {
|
||||
verify, err := config.VerifyRemoteCert()
|
||||
if err != nil {
|
||||
log.Errorf("failed to check whether insecure or not: %v", err)
|
||||
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
|
||||
}
|
||||
registry, err := newRegistryClient(endpoint, !verify, username, password)
|
||||
func (t *TargetAPI) ping(endpoint, username, password string, insecure bool) {
|
||||
registry, err := newRegistryClient(endpoint, insecure, username, password)
|
||||
if err != nil {
|
||||
// timeout, dns resolve error, connection refused, etc.
|
||||
if urlErr, ok := err.(*url.Error); ok {
|
||||
|
@ -105,6 +100,7 @@ func (t *TargetAPI) PingByID() {
|
|||
endpoint := target.URL
|
||||
username := target.Username
|
||||
password := target.Password
|
||||
insecure := target.Insecure
|
||||
if len(password) != 0 {
|
||||
password, err = utils.ReversibleDecrypt(password, t.secretKey)
|
||||
if err != nil {
|
||||
|
@ -112,7 +108,7 @@ func (t *TargetAPI) PingByID() {
|
|||
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
|
||||
}
|
||||
}
|
||||
t.ping(endpoint, username, password)
|
||||
t.ping(endpoint, username, password, insecure)
|
||||
}
|
||||
|
||||
// Ping validates whether the target is reachable and whether the credential is valid
|
||||
|
@ -121,6 +117,7 @@ func (t *TargetAPI) Ping() {
|
|||
Endpoint string `json:"endpoint"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Insecure bool `json:"insecure"`
|
||||
}{}
|
||||
t.DecodeJSONReq(&req)
|
||||
|
||||
|
@ -128,7 +125,7 @@ func (t *TargetAPI) Ping() {
|
|||
t.CustomAbort(http.StatusBadRequest, "endpoint is required")
|
||||
}
|
||||
|
||||
t.ping(req.Endpoint, req.Username, req.Password)
|
||||
t.ping(req.Endpoint, req.Username, req.Password, req.Insecure)
|
||||
}
|
||||
|
||||
// Get ...
|
||||
|
@ -255,6 +252,7 @@ func (t *TargetAPI) Put() {
|
|||
Endpoint *string `json:"endpoint"`
|
||||
Username *string `json:"username"`
|
||||
Password *string `json:"password"`
|
||||
Insecure *bool `json:"insecure"`
|
||||
}{}
|
||||
t.DecodeJSONReq(&req)
|
||||
|
||||
|
@ -273,6 +271,9 @@ func (t *TargetAPI) Put() {
|
|||
if req.Password != nil {
|
||||
target.Password = *req.Password
|
||||
}
|
||||
if req.Insecure != nil {
|
||||
target.Insecure = *req.Insecure
|
||||
}
|
||||
|
||||
t.Validate(target)
|
||||
|
||||
|
|
|
@ -276,15 +276,6 @@ func OnlyAdminCreateProject() (bool, error) {
|
|||
return cfg[common.ProjectCreationRestriction].(string) == common.ProCrtRestrAdmOnly, nil
|
||||
}
|
||||
|
||||
// VerifyRemoteCert returns bool value.
|
||||
func VerifyRemoteCert() (bool, error) {
|
||||
cfg, err := mg.Get()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
return cfg[common.VerifyRemoteCert].(bool), nil
|
||||
}
|
||||
|
||||
// Email returns email server settings
|
||||
func Email() (*models.Email, error) {
|
||||
cfg, err := mg.Get()
|
||||
|
|
|
@ -108,10 +108,6 @@ func TestConfig(t *testing.T) {
|
|||
t.Fatalf("failed to get onldy admin create project: %v", err)
|
||||
}
|
||||
|
||||
if _, err := VerifyRemoteCert(); err != nil {
|
||||
t.Fatalf("failed to get verify remote cert: %v", err)
|
||||
}
|
||||
|
||||
if _, err := Email(); err != nil {
|
||||
t.Fatalf("failed to get email settings: %v", err)
|
||||
}
|
||||
|
|
|
@ -38,6 +38,10 @@ export const CREATE_EDIT_ENDPOINT_TEMPLATE: string = `
|
|||
<label for="destination_password" class="col-md-4 form-group-label-override">{{ 'DESTINATION.PASSWORD' | translate }}</label>
|
||||
<input type="password" class="col-md-8" id="destination_password" [disabled]="testOngoing" [readonly]="!editable" [(ngModel)]="target.password" size="20" name="password" #password="ngModel" (focus)="clearPassword($event)">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="destination_insecure" class="col-md-4 form-group-label-override">{{'CONFIG.VERIFY_REMOTE_CERT' | translate }}</label>
|
||||
<clr-checkbox #insecure class="col-md-8" name="insecure" id="destination_insecure" [(ngModel)]="target.insecure"></clr-checkbox>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="spin" class="col-md-4"></label>
|
||||
<span class="col-md-8 spinner spinner-inline" [hidden]="!inProgress"></span>
|
||||
|
|
|
@ -21,6 +21,7 @@ describe('CreateEditEndpointComponent (inline template)', () => {
|
|||
"name": "target_01",
|
||||
"username": "admin",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
};
|
||||
|
||||
|
|
|
@ -91,7 +91,8 @@ export class CreateEditEndpointComponent implements AfterViewChecked, OnDestroy
|
|||
(this.target.endpoint && this.target.endpoint.trim() !== "") ||
|
||||
(this.target.name && this.target.name.trim() !== "") ||
|
||||
(this.target.username && this.target.username.trim() !== "") ||
|
||||
(this.target.password && this.target.password.trim() !== ""));
|
||||
(this.target.password && this.target.password.trim() !== "")) ||
|
||||
this.target.insecure;
|
||||
} else {
|
||||
//Edit
|
||||
return !compareValue(this.target, this.initVal);
|
||||
|
@ -104,26 +105,29 @@ export class CreateEditEndpointComponent implements AfterViewChecked, OnDestroy
|
|||
this.targetForm &&
|
||||
this.targetForm.valid &&
|
||||
this.editable &&
|
||||
(this.targetNameHasChanged || this.endpointHasChanged);
|
||||
(this.targetNameHasChanged || this.endpointHasChanged || this.checkboxHasChanged);
|
||||
}
|
||||
|
||||
public get inProgress(): boolean {
|
||||
return this.onGoing || this.testOngoing;
|
||||
}
|
||||
|
||||
public get checkboxHasChanged(): boolean {
|
||||
return (this.target.insecure !== this.initVal.insecure) ? true : false;
|
||||
}
|
||||
ngOnDestroy(): void {
|
||||
if (this.valueChangesSub) {
|
||||
this.valueChangesSub.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
initEndpoint(): Endpoint {
|
||||
return {
|
||||
endpoint: "",
|
||||
name: "",
|
||||
username: "",
|
||||
password: "",
|
||||
insecure: false,
|
||||
type: 0
|
||||
};
|
||||
}
|
||||
|
@ -275,20 +279,28 @@ export class CreateEditEndpointComponent implements AfterViewChecked, OnDestroy
|
|||
if (this.onGoing) {
|
||||
return;//Avoid duplicated submitting
|
||||
}
|
||||
if (!(this.targetNameHasChanged || this.endpointHasChanged)) {
|
||||
if (!(this.targetNameHasChanged || this.endpointHasChanged || this.checkboxHasChanged)) {
|
||||
return;//Avoid invalid submitting
|
||||
}
|
||||
let payload: Endpoint = this.initEndpoint();
|
||||
if (this.targetNameHasChanged) {
|
||||
payload.name = this.target.name;
|
||||
delete payload.endpoint;
|
||||
}else {
|
||||
delete payload.name;
|
||||
}
|
||||
if (this.endpointHasChanged) {
|
||||
payload.endpoint = this.target.endpoint;
|
||||
payload.username = this.target.username;
|
||||
payload.password = this.target.password;
|
||||
delete payload.name;
|
||||
}else {
|
||||
delete payload.endpoint;
|
||||
}
|
||||
if (this.checkboxHasChanged) {
|
||||
payload.insecure = this.target.insecure;
|
||||
}else {
|
||||
delete payload.insecure;
|
||||
}
|
||||
|
||||
if (!this.target.id) { return; }
|
||||
|
||||
this.onGoing = true;
|
||||
|
@ -317,7 +329,7 @@ export class CreateEditEndpointComponent implements AfterViewChecked, OnDestroy
|
|||
|
||||
handleErrorMessageKey(status: number): string {
|
||||
switch (status) {
|
||||
case 409: this
|
||||
case 409:
|
||||
return 'DESTINATION.CONFLICT_NAME';
|
||||
case 400:
|
||||
return 'DESTINATION.INVALID_NAME';
|
||||
|
@ -356,7 +368,7 @@ export class CreateEditEndpointComponent implements AfterViewChecked, OnDestroy
|
|||
keyNumber++;
|
||||
}
|
||||
}
|
||||
if (keyNumber !== 4) {
|
||||
if (keyNumber !== 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ describe('CreateEditRuleComponent (inline template)', ()=>{
|
|||
"name": "target_01",
|
||||
"username": "admin",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
|
@ -118,6 +119,7 @@ describe('CreateEditRuleComponent (inline template)', ()=>{
|
|||
"name": "target_02",
|
||||
"username": "AAA",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
|
@ -126,6 +128,7 @@ describe('CreateEditRuleComponent (inline template)', ()=>{
|
|||
"name": "target_03",
|
||||
"username": "admin",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
|
@ -134,6 +137,7 @@ describe('CreateEditRuleComponent (inline template)', ()=>{
|
|||
"name": "target_04",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"insecure": true,
|
||||
"type": 0
|
||||
}
|
||||
];
|
||||
|
|
|
@ -123,6 +123,7 @@ export class CreateEditRuleComponent implements AfterViewChecked {
|
|||
name: '',
|
||||
username: '',
|
||||
password: '',
|
||||
insecure: false,
|
||||
type: 0
|
||||
};
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ export const ENDPOINT_TEMPLATE: string = `
|
|||
<clr-datagrid [clrDgLoading]="loading">
|
||||
<clr-dg-column [clrDgField]="'name'">{{'DESTINATION.NAME' | translate}}</clr-dg-column>
|
||||
<clr-dg-column [clrDgField]="'endpoint'">{{'DESTINATION.URL' | translate}}</clr-dg-column>
|
||||
<clr-dg-column [clrDgField]="'insecure'">{{'CONFIG.VERIFY_REMOTE_CERT' | translate }}</clr-dg-column>
|
||||
<clr-dg-column [clrDgSortBy]="creationTimeComparator">{{'DESTINATION.CREATION_TIME' | translate}}</clr-dg-column>
|
||||
<clr-dg-placeholder>{{'DESTINATION.PLACEHOLDER' | translate }}</clr-dg-placeholder>
|
||||
<clr-dg-row *clrDgItems="let t of targets" [clrDgItem]='t'>
|
||||
|
@ -28,6 +29,9 @@ export const ENDPOINT_TEMPLATE: string = `
|
|||
</clr-dg-action-overflow>
|
||||
<clr-dg-cell>{{t.name}}</clr-dg-cell>
|
||||
<clr-dg-cell>{{t.endpoint}}</clr-dg-cell>
|
||||
<clr-dg-cell>
|
||||
<clr-checkbox name="insecure" [clrChecked]="t.insecure"> </clr-checkbox>
|
||||
</clr-dg-cell>
|
||||
<clr-dg-cell>{{t.creation_time | date: 'short'}}</clr-dg-cell>
|
||||
</clr-dg-row>
|
||||
<clr-dg-footer>
|
||||
|
|
|
@ -25,6 +25,7 @@ describe('EndpointComponent (inline template)', () => {
|
|||
"name": "target_01",
|
||||
"username": "admin",
|
||||
"password": "",
|
||||
"insecure": true,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
|
@ -33,6 +34,7 @@ describe('EndpointComponent (inline template)', () => {
|
|||
"name": "target_02",
|
||||
"username": "AAA",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
|
@ -41,6 +43,7 @@ describe('EndpointComponent (inline template)', () => {
|
|||
"name": "target_03",
|
||||
"username": "admin",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
|
@ -49,6 +52,7 @@ describe('EndpointComponent (inline template)', () => {
|
|||
"name": "target_04",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
}
|
||||
];
|
||||
|
@ -59,6 +63,7 @@ describe('EndpointComponent (inline template)', () => {
|
|||
"name": "target_01",
|
||||
"username": "admin",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
};
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ export class EndpointComponent implements OnInit {
|
|||
name: "",
|
||||
username: "",
|
||||
password: "",
|
||||
insecure: false,
|
||||
type: 0
|
||||
};
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ describe('Replication Component (inline template)', ()=>{
|
|||
"name": "target_01",
|
||||
"username": "admin",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
|
@ -115,6 +116,7 @@ describe('Replication Component (inline template)', ()=>{
|
|||
"name": "target_02",
|
||||
"username": "AAA",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
|
@ -123,6 +125,7 @@ describe('Replication Component (inline template)', ()=>{
|
|||
"name": "target_03",
|
||||
"username": "admin",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
},
|
||||
{
|
||||
|
@ -131,6 +134,7 @@ describe('Replication Component (inline template)', ()=>{
|
|||
"name": "target_04",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"insecure": false,
|
||||
"type": 0
|
||||
}
|
||||
];
|
||||
|
|
|
@ -73,6 +73,7 @@ export interface Endpoint extends Base {
|
|||
name: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
insecure: boolean;
|
||||
type: number;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"clarity-icons": "^0.9.8",
|
||||
"clarity-ui": "^0.9.8",
|
||||
"core-js": "^2.4.1",
|
||||
"harbor-ui": "0.4.83",
|
||||
"harbor-ui": "0.4.85",
|
||||
"intl": "^1.2.5",
|
||||
"mutationobserver-shim": "^0.3.2",
|
||||
"ngx-cookie": "^1.0.0",
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
<li role="presentation" class="nav-item">
|
||||
<button id="config-auth" class="btn btn-link nav-link active" aria-controls="authentication" [class.active]='isCurrentTabLink("config-auth")' type="button" (click)='tabLinkClick("config-auth")'>{{'CONFIG.AUTH' | translate }}</button>
|
||||
</li>
|
||||
<li role="presentation" class="nav-item">
|
||||
<button id="config-replication" class="btn btn-link nav-link" aria-controls="replication" [class.active]='isCurrentTabLink("config-replication")' type="button" (click)='tabLinkClick("config-replication")'>{{'CONFIG.REPLICATION' | translate }}</button>
|
||||
</li>
|
||||
<li role="presentation" class="nav-item">
|
||||
<button id="config-email" class="btn btn-link nav-link" aria-controls="email" [class.active]='isCurrentTabLink("config-email")' type="button" (click)='tabLinkClick("config-email")'>{{'CONFIG.EMAIL' | translate }}</button>
|
||||
</li>
|
||||
|
@ -22,9 +19,6 @@
|
|||
<section id="authentication" role="tabpanel" aria-labelledby="config-auth" [hidden]='!isCurrentTabContent("authentication")'>
|
||||
<config-auth [ldapConfig]="allConfig"></config-auth>
|
||||
</section>
|
||||
<section id="replication" role="tabpanel" aria-labelledby="config-replication" [hidden]='!isCurrentTabContent("replication")'>
|
||||
<replication-config [(replicationConfig)]="allConfig"></replication-config>
|
||||
</section>
|
||||
<section id="email" role="tabpanel" aria-labelledby="config-email" [hidden]='!isCurrentTabContent("email")'>
|
||||
<config-email [mailConfig]="allConfig"></config-email>
|
||||
</section>
|
||||
|
|
|
@ -30,7 +30,6 @@ import {
|
|||
Configuration,
|
||||
StringValueItem,
|
||||
ComplexValueItem,
|
||||
ReplicationConfigComponent,
|
||||
SystemSettingsComponent,
|
||||
VulnerabilityConfigComponent,
|
||||
ClairDBStatus
|
||||
|
@ -59,7 +58,6 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||
testingMailOnGoing: boolean = false;
|
||||
testingLDAPOnGoing: boolean = false;
|
||||
|
||||
@ViewChild(ReplicationConfigComponent) replicationConfig: ReplicationConfigComponent;
|
||||
@ViewChild(SystemSettingsComponent) systemSettingsConfig: SystemSettingsComponent;
|
||||
@ViewChild(VulnerabilityConfigComponent) vulnerabilityConfig: VulnerabilityConfigComponent;
|
||||
@ViewChild(ConfigurationEmailComponent) mailConfig: ConfigurationEmailComponent;
|
||||
|
@ -170,9 +168,7 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
public isValid(): boolean {
|
||||
return this.replicationConfig &&
|
||||
this.replicationConfig.isValid &&
|
||||
this.systemSettingsConfig &&
|
||||
return this.systemSettingsConfig &&
|
||||
this.systemSettingsConfig.isValid &&
|
||||
this.mailConfig &&
|
||||
this.mailConfig.isValid() &&
|
||||
|
|
|
@ -102,7 +102,7 @@ Project Creation Should Not Display
|
|||
Switch To System Settings
|
||||
Sleep 1
|
||||
Click Element xpath=//clr-main-container//nav//ul/li[3]
|
||||
Click Element xpath=//config//ul/li[4]
|
||||
Click Element xpath=//*[@id="config-system"]
|
||||
|
||||
Modify Token Expiration
|
||||
[Arguments] ${minutes}
|
||||
|
|
|
@ -176,23 +176,6 @@ Test Case - Edit Self-Registration
|
|||
Enable Self Reg
|
||||
Close Browser
|
||||
|
||||
Test Case - Edit Verify Remote Cert
|
||||
Init Chrome Driver
|
||||
Sign In Harbor ${HARBOR_URL} %{HARBOR_ADMIN} %{HARBOR_PASSWORD}
|
||||
|
||||
Switch To System Replication
|
||||
Check Verify Remote Cert
|
||||
|
||||
Logout Harbor
|
||||
Sign In Harbor ${HARBOR_URL} %{HARBOR_ADMIN} %{HARBOR_PASSWORD}
|
||||
|
||||
Switch To System Replication
|
||||
Should Verify Remote Cert Be Enabled
|
||||
|
||||
#restore setting
|
||||
Check Verify Remote Cert
|
||||
Close Browser
|
||||
|
||||
Test Case - Edit Email Settings
|
||||
Init Chrome Driver
|
||||
Sign In Harbor ${HARBOR_URL} %{HARBOR_ADMIN} %{HARBOR_PASSWORD}
|
||||
|
|
|
@ -54,4 +54,5 @@ Changelog for harbor database schema
|
|||
|
||||
- create table `project_metadata`
|
||||
- insert data into table `project_metadata`
|
||||
- delete column `public` from table `project`
|
||||
- delete column `public` from table `project`
|
||||
- add column `insecure` to table `replication_target`
|
||||
|
|
Loading…
Reference in New Issue