diff options
author | Martin Stockhammer <martin_s@apache.org> | 2021-01-10 16:03:55 +0100 |
---|---|---|
committer | Martin Stockhammer <martin_s@apache.org> | 2021-01-10 16:03:55 +0100 |
commit | 29679e81293d00f8bb8b7513021c66ea010e4e81 (patch) | |
tree | 93d8134664599b399942fc5d9ce7dfa8548cd0cf | |
parent | cb3c2e2e041577df0de25f9c5b6c180cd58bc491 (diff) | |
download | archiva-29679e81293d00f8bb8b7513021c66ea010e4e81.tar.gz archiva-29679e81293d00f8bb8b7513021c66ea010e4e81.zip |
Adding ldap configuration
13 files changed, 232 insertions, 79 deletions
diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/bean-information.spec.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/bean-information.spec.ts index 138cadce8..b39928ed3 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/bean-information.spec.ts +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/bean-information.spec.ts @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + import { BeanInformation } from './bean-information'; describe('BeanInformation', () => { diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/bean-information.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/bean-information.ts index 379262ab4..9a561dba1 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/bean-information.ts +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/bean-information.ts @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + export class BeanInformation { id: string; display_name: string; diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/model/page-query.spec.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/ldap-configuration.spec.ts index 13b03a103..5c11c78c0 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/model/page-query.spec.ts +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/ldap-configuration.spec.ts @@ -16,10 +16,10 @@ * under the License. */ -import { PageQuery } from './page-query'; +import { LdapConfiguration } from './ldap-configuration'; -describe('PageQuery', () => { +describe('LdapConfiguration', () => { it('should create an instance', () => { - expect(new PageQuery()).toBeTruthy(); + expect(new LdapConfiguration()).toBeTruthy(); }); }); diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/directives/nav-subgroup.directive.spec.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/ldap-configuration.ts index 295d6c076..94b64369c 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/directives/nav-subgroup.directive.spec.ts +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/model/ldap-configuration.ts @@ -16,11 +16,17 @@ * under the License. */ -import { NavSubgroupDirective } from './nav-subgroup.directive'; - -describe('NavSubgroupDirective', () => { - it('should create an instance', () => { - const directive = new NavSubgroupDirective(); - expect(directive).toBeTruthy(); - }); -}); +export class LdapConfiguration { + host_name : string = ""; + port : number = -1; + ssl_enabled : boolean = false; + base_dn : string = ""; + groups_base_dn : string = ""; + bind_dn : string = ""; + bind_password : string = ""; + authentication_method : string = ""; + bind_authenticator_enabled : boolean = true; + use_role_name_as_group : boolean = false; + properties : Map<string,string> = new Map<string, string>() + writable : boolean = false; +} diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/base-security/base-security.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/base-security/base-security.component.html index fcf545f2a..79945d011 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/base-security/base-security.component.html +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/base-security/base-security.component.html @@ -17,6 +17,8 @@ --> <form class="mt-3 mb-3" [formGroup]="userForm" (ngSubmit)="onSubmit()"> + <h4>{{'security.config.base.head_managers'|translate}}</h4> + <p class="col-md-8">{{'security.config.base.explain_user_manager'|translate}}</p> <div class="row"> <div class="col-md-4"> <div class="drag-container"> @@ -38,6 +40,7 @@ </div> </div> + <p class="col-md-8">{{'security.config.base.explain_rbac_manager'|translate}}</p> <div class="row"> <div class="col-md-4"> <div class="drag-container"> @@ -58,6 +61,7 @@ </div> </div> </div> + <h4>{{'security.config.base.head_flags'|translate}}</h4> <div class="form-group row col-md-8"> <div class="col-md-2">{{'security.config.base.flags'|translate}}</div> <div class="col-md-4"> diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/base-security/base-security.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/base-security/base-security.component.ts index 4b3acf521..04134e9f9 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/base-security/base-security.component.ts +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/base-security/base-security.component.ts @@ -48,6 +48,17 @@ export class BaseSecurityComponent extends EditBaseComponent<SecurityConfigurati rbacInfo: Map<string,BeanInformation> = new Map<string, BeanInformation>(); userInfo: Map<string,BeanInformation> = new Map<string, BeanInformation>(); + constructor(private route: ActivatedRoute, + public fb: FormBuilder, private securityService: SecurityService, private toastService: ToastService) { + super(fb); + super.init(fb.group({ + user_cache_enabled:[''], + }, {})); + + + + } + drop(event: CdkDragDrop<string[]>) { console.log("Drop " + event); if (event.previousContainer === event.container) { @@ -60,17 +71,8 @@ export class BaseSecurityComponent extends EditBaseComponent<SecurityConfigurati } } - constructor(private route: ActivatedRoute, - public fb: FormBuilder, private securityService: SecurityService, private toastService: ToastService) { - super(fb); - super.init(fb.group({ - user_cache_enabled:[''], - }, {})); - - } - ngOnInit(): void { zip(this.securityService.getRbacManagers(),this.securityService.getUserManagers()).pipe(tap(([rbacInfo,userInfo])=>{ rbacInfo.forEach(info => this.rbacInfo.set(info.id, info)); diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.html b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.html index 55895d827..e98239894 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.html +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.html @@ -16,4 +16,35 @@ ~ under the License. --> -<p>ldap-security works!</p> +<form class="mt-3 mb-3" [formGroup]="userForm" (ngSubmit)="onSubmit()"> + <p class="row col-md-10">{{'security.config.ldap.explain'|translate}}</p> + <div class="form-group row col-md-10" *ngFor="let attName of ['host_name','port','base_dn','groups_base_dn','bind_dn','bind_password']"> + <label class="col-md-3 col-form-label" for="{{attName}}">{{'security.config.ldap.attributes.'+attName |translate}}</label> + <div [attr.class]="attName=='port'?'col-md-3':'col-md-7'"> + <input [attr.type]="attName=='bind_password'?'password':'text'" formControlName="{{attName}}" id="{{attName}}" + [ngClass]="getInputClasses(attName)" + > + </div> + </div> + <div class="form-group row col-md-10" > + <label class="col-md-3 col-form-label" for="authentication_method">{{'security.config.ldap.attributes.authentication_method' |translate}}</label> + <div class="col-md-2"> + <select formControlName="authentication_method" id="authentication_method" class="form-control"> + <option *ngFor="let method of authenticationMethods">{{method}}</option> + </select> + </div> + </div> + <div class="form-group row col-md-10"> + <div class="col-md-3">{{'security.config.ldap.flags'|translate}}</div> + <div class="col-md-7"> + <div class="form-check" *ngFor="let flagName of ['writable','ssl_enabled','bind_authenticator_enabled','use_role_name_as_group']"> + <input class="form-check-input" type="checkbox" formControlName="{{flagName}}" + id="{{flagName}}" > + <label class="form-check-label " for="{{flagName}}"> + {{'security.config.ldap.attributes.'+flagName|translate}} + </label> + </div> + </div> + </div> + +</form> diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.spec.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.spec.ts index 7de23ee3f..85bcf6b6a 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.spec.ts +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.spec.ts @@ -18,7 +18,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { LdapSecurityComponent } from './ldap-security.component'; +import { LdapSecurityComponent, dnValidator } from './ldap-security.component'; +import {ValidatorFn} from "@angular/forms"; describe('LdapSecurityComponent', () => { let component: LdapSecurityComponent; @@ -40,4 +41,17 @@ describe('LdapSecurityComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + describe('Test Custom DN Validator', () => { + it('check valid 1', () => { + const ctrl = component.userForm.controls['base_dn'] + ctrl.setValue('cn=abc'); + expect(ctrl.valid).toBeTruthy(); + }) + it('check invalid 1', () => { + const ctrl = component.userForm.controls['base_dn'] + ctrl.setValue('cn=abc,'); + expect(ctrl.invalid).toBeTruthy() + }) + }); }); diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.ts index 3c3b09588..7cc829eeb 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.ts +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/security-configuration/ldap-security/ldap-security.component.ts @@ -17,17 +17,102 @@ */ import { Component, OnInit } from '@angular/core'; +import {EditBaseComponent} from "@app/modules/shared/edit-base.component"; +import {LdapConfiguration} from "@app/model/ldap-configuration"; +import {ActivatedRoute} from "@angular/router"; +import {AbstractControl, FormBuilder, ValidatorFn, Validators} from "@angular/forms"; +import {SecurityService} from "@app/services/security.service"; +import {ToastService} from "@app/services/toast.service"; +import {propertyDescriptorPatch} from "zone.js/lib/browser/property-descriptor"; @Component({ selector: 'app-ldap-security', templateUrl: './ldap-security.component.html', styleUrls: ['./ldap-security.component.scss'] }) -export class LdapSecurityComponent implements OnInit { +export class LdapSecurityComponent extends EditBaseComponent<LdapConfiguration> implements OnInit { - constructor() { } + authenticationMethods=['none','simple','strong'] + + constructor(private route: ActivatedRoute, + public fb: FormBuilder, private securityService: SecurityService, private toastService: ToastService) { + super(fb); + super.init(fb.group({ + host_name:[''], + port:['', [Validators.min(1), Validators.max(65535)]], + ssl_enabled:[false], + base_dn:['',[dnValidator()]], + groups_base_dn:['',[dnValidator()]], + bind_dn:['',[dnValidator()]], + bind_password:[''], + authentication_method:['none'], + bind_authenticator_enabled:[false], + use_role_name_as_group:[true], + writable:[false] + }, {})); + } ngOnInit(): void { } + createEntity(): LdapConfiguration { + return new LdapConfiguration(); + } + + onSubmit() { + } + + getInputClasses(field: string) : string[] { + let csClasses = super.isValid(field); + if (csClasses.length==1 && csClasses[0]=='') { + csClasses = []; + } + csClasses.push('form-control'); + console.log("Classes "+field+" " + csClasses); + return csClasses; + } +} + +export function dnValidator(): ValidatorFn { + return (control: AbstractControl): {[key: string]: any} | null => { + let parts = [] + let value = control.value.toString() + let escape = false; + let partKey : string = '' + let partValue : string = '' + let key = true; + for (let i=0; i<value.length; i+=1) { + let c = value.charAt(i); + if (c=='\\' && !escape) { + escape = true; + } else if (c==',' && !escape) { + parts.push( [partKey,partValue]); + if (partKey.length==0) { + return {'invalidDnBadKey':{value:value,index:i}} + } + if (partValue.length==0) { + return {'invalidDnBadValue':{value:value, index: i}} + } + partKey=''; + partValue=''; + key=true; + continue; + } else if (c=='=' && !escape) { + if (!key) { + return {'invalidDnBadEquals':{value: value, index:i}} + } + key=false; + continue; + } else if (escape) { + escape = false; + } + if (key) { + partKey = partKey + c; + } else { + partValue = partValue + c; + } + + } + return null; + }; } diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts index 9608bba0b..cd2d3fcaa 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users-roles/manage-users-roles.component.ts @@ -24,10 +24,9 @@ import {catchError, filter, map, share, switchMap, tap} from "rxjs/operators"; import {RoleTree} from "@app/model/role-tree"; import {RoleService} from "@app/services/role.service"; import {RoleTemplate} from "@app/model/role-template"; -import {Observable} from "rxjs"; +import {from, Observable} from "rxjs"; import {Util} from "@app/modules/shared/shared.module"; import {RoleResult} from './role-result'; -import {fromArray} from "rxjs/internal/observable/fromArray"; import {ErrorResult} from "@app/model/error-result"; import {HttpResponse} from "@angular/common/http"; @@ -309,7 +308,7 @@ export class ManageUsersRolesComponent implements OnInit, AfterViewInit { }) } ) - fromArray(assignments).pipe(switchMap((role) => this.roleService.assignRole(role.id, this.userid)), + from(assignments).pipe(switchMap((role) => this.roleService.assignRole(role.id, this.userid)), catchError((err: ErrorResult, caught) => { this.success = false; this.errors.push(err); @@ -321,7 +320,7 @@ export class ManageUsersRolesComponent implements OnInit, AfterViewInit { this.saved=true; } ); - fromArray(unassignments).pipe(switchMap((role) => this.roleService.unAssignRole(role.id, this.userid)), + from(unassignments).pipe(switchMap((role) => this.roleService.unAssignRole(role.id, this.userid)), catchError((err: ErrorResult, caught) => { this.success = false; this.errors.push(err); diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.ts index 8ad6c3ef7..16347d9d8 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.ts +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/security/users/manage-users/manage-users.component.ts @@ -16,12 +16,10 @@ * under the License. */ -import {AfterViewInit, Component, OnInit} from '@angular/core'; -import {ActivatedRoute, Params} from "@angular/router"; -import {iif, Observable, of, pipe, merge, combineLatest} from "rxjs"; -import {combineAll, filter, map, mergeMap, share, switchMap, tap} from 'rxjs/operators'; -import {flatMap} from "rxjs/internal/operators"; -import {fromArray} from "rxjs/internal/observable/fromArray"; +import {Component, OnInit} from '@angular/core'; +import {ActivatedRoute} from "@angular/router"; +import {merge, Observable} from "rxjs"; +import {map} from 'rxjs/operators'; @Component({ selector: 'app-manage-users', diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/paginated-entities/paginated-entities.component.spec.ts b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/paginated-entities/paginated-entities.component.spec.ts deleted file mode 100644 index 0bd4fc801..000000000 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/app/modules/shared/paginated-entities/paginated-entities.component.spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { PaginatedEntitiesComponent } from './paginated-entities.component'; - -describe('PaginatedEntitiesComponent', () => { - let component: PaginatedEntitiesComponent; - let fixture: ComponentFixture<PaginatedEntitiesComponent>; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ PaginatedEntitiesComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PaginatedEntitiesComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json index 834a1a21a..5bffc1412 100644 --- a/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json +++ b/archiva-modules/archiva-web/archiva-webapp/src/main/archiva-web/src/assets/i18n/en.json @@ -176,6 +176,11 @@ "config": { "base": { "head": "Base Configuration", + "title": "Configure base security settings", + "head_managers": "Set the used User and RBAC managers", + "head_flags": "Additional flags", + "explain_user_manager": "User managers are binding your User IDs and authentication to a persistent storage or repository. You may combine them, but you have to ensure, that user IDs are unique over all repositories.", + "explain_rbac_manager": "RBAC managers handle roles and permissions and store them persistently. If you use LDAP, the roles are mapped to LDAP groups.", "flags": "Flags", "user_manager" : { "active_list" : "Active User Managers", @@ -189,12 +194,28 @@ "ldap_active": "LDAP Active", "user_cache_enabled": "User Cache Enabled" }, - "submit_success": "The Changes were submitted successfully", + "submit_success": "The Changes were submitted successfully. A restart may be required to activate the changes.", "submit_error": "There was an error during submit: {error}", "submit_active_empty": "There must be at least on active User and RBAC Manager defined" }, "ldap": { - "head": "LDAP Configuration" + "head": "LDAP Configuration", + "explain": "Settings for the LDAP connection. These settings are only used, if LDAP User Manager and/or LDAP RBAC Manager is activated.", + "attributes": { + "host_name": "Host Name", + "port": "Port", + "base_dn": "Base DN", + "groups_base_dn": "Base DN for Group Search", + "bind_dn": "Bind User DN", + "bind_password":"Bind Password", + "authentication_method": "Method used for Bind Authentication", + "bind_authenticator_enabled": "Use LDAP Bind during archiva authentication", + "use_role_name_as_group": "Archiva role names are LDAP group names", + "writable": "Bind User can write to LDAP Server", + "ssl_enabled": "Enable SSL" + + }, + "flags": "Flags" } } }, |