mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-12 18:01:54 +01:00
Merge pull request #3416 from ywk253100/171020_insecure_target
Move certificate verification to target level
This commit is contained in:
commit
4d4b27b400
@ -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
Block a user